e233f1ce4c01a2cfd308da591e1ad149ea055e98
[firefly-linux-kernel-4.4.55.git] / drivers / video / rk29_fb.c
1 /*
2  * drivers/video/rk29_fb.c
3  *
4  * Copyright (C) 2010 ROCKCHIP, Inc.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/string.h>
20 #include <linux/mm.h>
21 #include <linux/slab.h>
22 #include <linux/delay.h>
23 #include <linux/device.h>
24 #include <linux/fb.h>
25 #include <linux/init.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/interrupt.h>
28 #include <linux/platform_device.h>
29 #include <linux/clk.h>
30 #include <linux/backlight.h>
31 #include <linux/timer.h>
32 #include <linux/time.h>
33 #include <linux/wait.h>
34 #include <linux/earlysuspend.h>
35 #include <linux/cpufreq.h>
36
37
38 #include <asm/io.h>
39 #include <asm/div64.h>
40 #include <asm/uaccess.h>
41
42 #include "rk29_fb.h"
43
44 #ifdef CONFIG_PM
45 #include <linux/pm.h>
46 #endif
47
48 #include <mach/iomux.h>
49 #include <mach/gpio.h>
50 #include <mach/board.h>
51 #include <mach/rk29_iomap.h>
52 //#include <asm/uaccess.h>
53
54 #include "./display/screen/screen.h"
55
56
57 #if 0
58         #define fbprintk(msg...)        printk(msg);
59 #else
60         #define fbprintk(msg...)
61 #endif
62
63
64 #if 0
65         #define fbprintk2(msg...)       printk(msg);
66 #else
67         #define fbprintk2(msg...)
68 #endif
69
70 #define LcdReadBit(inf, addr, msk)      ((inf->regbak.addr=inf->preg->addr)&(msk))
71 #define LcdWrReg(inf, addr, val)        inf->preg->addr=inf->regbak.addr=(val)
72 #define LcdRdReg(inf, addr)             (inf->preg->addr)
73 #define LcdSetBit(inf, addr, msk)       inf->preg->addr=((inf->regbak.addr) |= (msk))
74 #define LcdClrBit(inf, addr, msk)       inf->preg->addr=((inf->regbak.addr) &= ~(msk))
75 #define LcdSetRegBit(inf, addr, msk)    inf->preg->addr=((inf->preg->addr) |= (msk))
76 #define LcdMskReg(inf, addr, msk, val)  (inf->regbak.addr)&=~(msk);   inf->preg->addr=(inf->regbak.addr|=(val))
77
78
79 #define IsMcuLandscape()                ((SCREEN_MCU==inf->cur_screen->type) && (0==inf->mcu_scandir))
80 #define IsMcuUseFmk()                   ( (2==inf->cur_screen->mcu_usefmk) || (1==inf->cur_screen->mcu_usefmk))
81
82 #define CalScaleW0(x, y)                     (((u32)x*0x1000)/y)
83
84 struct rk29fb_rgb {
85         struct fb_bitfield      red;
86         struct fb_bitfield      green;
87         struct fb_bitfield      blue;
88         struct fb_bitfield      transp;
89 };
90
91 static struct rk29fb_rgb def_rgb_16 = {
92      red:    { offset: 11, length: 5, },
93      green:  { offset: 5,  length: 6, },
94      blue:   { offset: 0,  length: 5, },
95      transp: { offset: 0,  length: 0, },
96 };
97
98 struct win0_par {
99         u32 refcount;
100         u32     pseudo_pal[16];
101         u32 y_offset;
102         u32 uv_offset;
103     u32 xpos;         //size in panel
104     u32 ypos;
105     u32 xsize;        //start point in panel
106     u32 ysize;
107     u32 format;
108
109     u8 par_seted;
110     u8 addr_seted;
111 };
112
113 struct win1_par {
114         u32 refcount;
115         u32     pseudo_pal[16];
116         int lstblank;
117     u32 xpos;
118     u32 ypos;
119     u32 xsize;
120     u32 ysize;
121     u32 format;
122     u32 addr_offset;
123 };
124
125 struct rk29fb_inf {
126     struct fb_info *fb1;
127     struct fb_info *fb0;
128
129     void __iomem *reg_vir_base;  // virtual basic address of lcdc register
130         u32 reg_phy_base;       // physical basic address of lcdc register
131         u32 len;               // physical map length of lcdc register
132     u32 video_mode;
133
134     struct clk      *clk;
135     struct clk      *dclk;            //lcdc dclk
136     struct clk      *dclk_parent;     //lcdc dclk divider frequency source
137     struct clk      *dclk_divider;    //lcdc demodulator divider frequency
138     struct clk      *aclk;   //lcdc share memory frequency
139     struct clk      *aclk_parent;     //lcdc aclk divider frequency source
140     unsigned long       dclk_rate;
141
142     /* lcdc reg base address and backup reg */
143     LCDC_REG *preg;
144     LCDC_REG regbak;
145
146         int in_suspend;
147
148     /* variable used in mcu panel */
149         int mcu_needflush;
150         int mcu_isrcnt;
151         u16 mcu_scandir;
152         struct timer_list mcutimer;
153         int mcu_status;
154         u8 mcu_fmksync;
155         int mcu_usetimer;
156         int mcu_stopflush;
157
158     /* external memery */
159         char __iomem *screen_base2;
160     __u32 smem_len2;
161     unsigned long  smem_start2;
162
163     char __iomem *cursor_base;   /* cursor Virtual address*/
164     __u32 cursor_size;           /* Amount of ioremapped VRAM or 0 */
165     unsigned long  cursor_start;
166
167     struct rk29fb_screen panel1_info;         // 1st panel, it's lcd normally
168     struct rk29fb_screen panel2_info;         // 2nd panel
169     struct rk29fb_screen *cur_screen;
170 #ifdef CONFIG_CPU_FREQ
171     struct notifier_block freq_transition;
172 #endif
173
174 };
175
176 typedef enum _TRSP_MODE
177 {
178     TRSP_CLOSE = 0,
179     TRSP_FMREG,
180     TRSP_FMREGEX,
181     TRSP_FMRAM,
182     TRSP_FMRAMEX,
183     TRSP_MASK,
184     TRSP_INVAL
185 } TRSP_MODE;
186
187
188 struct platform_device *g_pdev = NULL;
189 static int win1fb_set_par(struct fb_info *info);
190
191 #if 0
192 #define CHK_SUSPEND(inf)        \
193         if(inf->in_suspend)     {       \
194                 fbprintk(">>>>>> fb is in suspend! return! \n");        \
195                 return -EPERM;  \
196         }
197 #else
198 #define CHK_SUSPEND(inf)
199 #endif
200
201 static DECLARE_WAIT_QUEUE_HEAD(wq);
202 static int wq_condition = 0;
203
204 void set_lcd_pin(struct platform_device *pdev, int enable)
205 {
206         struct rk29fb_info *mach_info = pdev->dev.platform_data;
207
208         unsigned display_on = mach_info->disp_on_pin;
209         unsigned lcd_standby = mach_info->standby_pin;
210
211         int display_on_pol = mach_info->disp_on_value;
212         int lcd_standby_pol = mach_info->standby_value;
213
214         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
215         fbprintk(">>>>>> display_on(%d) = %d \n", display_on, enable ? display_on_pol : !display_on_pol);
216         fbprintk(">>>>>> lcd_standby(%d) = %d \n", lcd_standby, enable ? lcd_standby_pol : !lcd_standby_pol);
217
218     // set display_on
219
220     if(display_on != INVALID_GPIO)
221     {
222         gpio_direction_output(display_on, 0);
223                 gpio_set_value(display_on, enable ? display_on_pol : !display_on_pol);
224     }
225     if(lcd_standby != INVALID_GPIO)
226     {
227         gpio_direction_output(lcd_standby, 0);
228                 gpio_set_value(lcd_standby, enable ? lcd_standby_pol : !lcd_standby_pol);
229     }
230 }
231
232 int mcu_do_refresh(struct rk29fb_inf *inf)
233 {
234     if(inf->mcu_stopflush)  return 0;
235
236     if(SCREEN_MCU!=inf->cur_screen->type)   return 0;
237
238     // use frame mark
239     if(IsMcuUseFmk())
240     {
241         inf->mcu_needflush = 1;
242         return 0;
243     }
244
245     // not use frame mark
246     if(LcdReadBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_SELECT))
247     {
248         if(!LcdReadBit(inf, MCU_TIMING_CTRL, m_MCU_HOLD_STATUS))
249         {
250             inf->mcu_needflush = 1;
251         }
252         else
253         {
254             if(inf->cur_screen->refresh)    inf->cur_screen->refresh(REFRESH_PRE);
255             inf->mcu_needflush = 0;
256             inf->mcu_isrcnt = 0;
257             LcdSetRegBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_FRAME_ST);
258         }
259     }
260     return 0;
261 }
262
263
264 void mcutimer_callback(unsigned long arg)
265 {
266     struct rk29fb_inf *inf = platform_get_drvdata(g_pdev);
267     static int waitcnt = 0;
268
269     mod_timer(&inf->mcutimer, jiffies + HZ/10);
270
271     switch(inf->mcu_status)
272     {
273     case MS_IDLE:
274         inf->mcu_status = MS_MCU;
275         break;
276     case MS_MCU:
277         if(inf->mcu_usetimer)   mcu_do_refresh(inf);
278         break;
279     case MS_EWAITSTART:
280         inf->mcu_status = MS_EWAITEND;
281         waitcnt = 0;
282         break;
283     case MS_EWAITEND:
284         if(0==waitcnt) {
285             mcu_do_refresh(inf);
286         }
287         if(waitcnt++>14) {
288             inf->mcu_status = MS_EEND;
289         }
290         break;
291     case MS_EEND:
292         inf->mcu_status = MS_MCU;
293         break;
294     default:
295         inf->mcu_status = MS_MCU;
296         break;
297     }
298 }
299
300 int mcu_refresh(struct rk29fb_inf *inf)
301 {
302     static int mcutimer_inited = 0;
303
304     if(SCREEN_MCU!=inf->cur_screen->type)   return 0;
305
306     if(!mcutimer_inited)
307     {
308         mcutimer_inited = 1;
309         init_timer(&inf->mcutimer);
310         inf->mcutimer.function = mcutimer_callback;
311         inf->mcutimer.expires = jiffies + HZ/5;
312         inf->mcu_status = MS_IDLE;
313         add_timer(&inf->mcutimer);
314     }
315
316     if(MS_MCU==inf->mcu_status)     mcu_do_refresh(inf);
317
318     return 0;
319 }
320
321 int mcu_ioctl(unsigned int cmd, unsigned long arg)
322 {
323     struct rk29fb_inf *inf = NULL;
324     if(!g_pdev)     return -1;
325
326     inf = dev_get_drvdata(&g_pdev->dev);
327
328     switch(cmd)
329     {
330     case MCU_WRCMD:
331         LcdClrBit(inf, MCU_TIMING_CTRL, m_MCU_RS_SELECT);
332         LcdWrReg(inf, MCU_BYPASS_WPORT, arg);
333         LcdSetBit(inf, MCU_TIMING_CTRL, m_MCU_RS_SELECT);
334         break;
335
336     case MCU_WRDATA:
337         LcdSetBit(inf, MCU_TIMING_CTRL, m_MCU_RS_SELECT);
338         LcdWrReg(inf, MCU_BYPASS_WPORT, arg);
339         break;
340
341     case MCU_SETBYPASS:
342         LcdMskReg(inf, MCU_TIMING_CTRL, m_MCU_BYPASSMODE_SELECT, v_MCU_BYPASSMODE_SELECT(arg));
343         LcdWrReg(inf, REG_CFG_DONE, 0x01);
344         break;
345
346     default:
347         break;
348     }
349
350     return 0;
351 }
352
353 static irqreturn_t mcu_irqfmk(int irq, void *dev_id)
354 {
355         struct platform_device *pdev = (struct platform_device*)dev_id;
356     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
357     struct rk29fb_screen *screen;
358
359     if(!inf)    return IRQ_HANDLED;
360
361     screen = inf->cur_screen;
362
363     if(0==screen->mcu_usefmk) {
364         return IRQ_HANDLED;
365     }
366
367     if(inf->mcu_fmksync == 1)
368         return IRQ_HANDLED;
369
370     inf->mcu_fmksync = 1;
371     if(inf->mcu_needflush)
372     {
373         inf->mcu_needflush = 0;
374         inf->mcu_isrcnt = 0;
375         if(inf->cur_screen->refresh)
376            inf->cur_screen->refresh(REFRESH_PRE);
377         LcdSetBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_FRAME_ST);
378     }
379     inf->mcu_fmksync = 0;
380
381         return IRQ_HANDLED;
382 }
383
384 int init_lcdc(struct fb_info *info)
385 {
386     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
387     u32 msk=0, clr=0;
388
389         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
390
391         // set AHB access rule and disable all windows
392     LcdWrReg(inf, SYS_CONFIG, 0x20000000);
393     LcdWrReg(inf, SWAP_CTRL, 0);
394     LcdWrReg(inf, FIFO_WATER_MARK, 0x00000860);
395
396         // and mcu holdmode; and set win1 top.
397     LcdMskReg(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_SELECT | m_MCU_HOLDMODE_FRAME_ST | m_MCU_BYPASSMODE_SELECT ,
398             v_MCU_HOLDMODE_SELECT(0)| v_MCU_HOLDMODE_FRAME_ST(0) |v_MCU_BYPASSMODE_SELECT(0));
399
400     // disable blank out, black out, tristate out, yuv2rgb bypass
401     LcdMskReg(inf, BLEND_CTRL,m_W2_BLEND_EN | m_W1_BLEND_EN | m_W0_BLEND_EN | m_HWC_BLEND_EN |
402              m_HWC_BLEND_FACTOR | m_W1_BLEND_FACTOR | m_W0_BLEND_FACTOR,
403              v_W2_BLEND_EN(0) |v_W1_BLEND_EN(0) | v_W0_BLEND_EN(0) | v_HWC_BLEND_EN(0) |
404              v_HWC_BLEND_FACTOR(0) | v_W2_BLEND_FACTOR(0) | v_W1_BLEND_FACTOR(0) | v_W0_BLEND_FACTOR(0)
405              );
406
407     LcdMskReg(inf, WIN0_COLOR_KEY_CTRL, m_COLORKEY_EN, v_COLORKEY_EN(0));
408     LcdMskReg(inf, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN, v_COLORKEY_EN(0));
409
410     LcdWrReg(inf, DSP_CTRL1, 0);
411
412     // initialize all interrupt
413     clr = v_HOR_STARTCLEAR(1) | v_FRM_STARTCLEAR(1) | v_SCANNING_CLEAR(1);
414
415     msk = v_HOR_STARTMASK(1) | v_FRM_STARTMASK(0) | v_SCANNING_MASK(1);
416
417     LcdWrReg(inf, INT_STATUS, clr | msk);
418
419         // let above to take effect
420     LcdWrReg(inf, REG_CFG_DONE, 0x01);
421
422     return 0;
423 }
424
425 void load_screen(struct fb_info *info, bool initscreen)
426 {
427     int ret = -EINVAL;
428     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
429     struct rk29fb_screen *screen = inf->cur_screen;
430     u16 face;
431     u16 mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend;
432     u16 right_margin = screen->right_margin, lower_margin = screen->lower_margin;
433     u16 x_res = screen->x_res, y_res = screen->y_res;
434     u32 aclk_rate = 150000000;
435
436     if(!g_pdev){
437         printk(">>>>>> %s : %s no g_pdev\n", __FILE__, __FUNCTION__);
438         return;
439     }
440
441         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
442
443     // set the rgb or mcu
444     LcdMskReg(inf, MCU_TIMING_CTRL, m_MCU_OUTPUT_SELECT, v_MCU_OUTPUT_SELECT((SCREEN_MCU==screen->type)?(1):(0)));
445
446         // set out format and mcu timing
447     mcu_total  = (screen->mcu_wrperiod*150*1000)/1000000;
448     if(mcu_total>31)    mcu_total = 31;
449     if(mcu_total<3)     mcu_total = 3;
450     mcu_rwstart = (mcu_total+1)/4 - 1;
451     mcu_rwend = ((mcu_total+1)*3)/4 - 1;
452     mcu_csstart = (mcu_rwstart>2) ? (mcu_rwstart-3) : (0);
453     mcu_csend = (mcu_rwend>15) ? (mcu_rwend-1) : (mcu_rwend);
454
455     fbprintk(">> mcu_total=%d, mcu_rwstart=%d, mcu_csstart=%d, mcu_rwend=%d, mcu_csend=%d \n",
456         mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend);
457
458     LcdMskReg(inf, MCU_TIMING_CTRL,
459              m_MCU_CS_ST | m_MCU_CS_END| m_MCU_RW_ST | m_MCU_RW_END |
460              m_MCU_WRITE_PERIOD | m_MCU_HOLDMODE_SELECT | m_MCU_HOLDMODE_FRAME_ST,
461             v_MCU_CS_ST(mcu_csstart) | v_MCU_CS_END(mcu_csend) | v_MCU_RW_ST(mcu_rwstart) |
462             v_MCU_RW_END(mcu_rwend) |  v_MCU_WRITE_PERIOD(mcu_total) |
463             v_MCU_HOLDMODE_SELECT((SCREEN_MCU==screen->type)?(1):(0)) | v_MCU_HOLDMODE_FRAME_ST(0)
464            );
465
466         // set synchronous pin polarity and data pin swap rule
467         switch (screen->face)
468         {
469         case OUT_P565:
470             face = OUT_P565;
471             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
472             break;
473         case OUT_P666:
474             face = OUT_P666;
475             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
476             break;
477         case OUT_D888_P565:
478             face = OUT_P888;
479             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
480             break;
481         case OUT_D888_P666:
482             face = OUT_P888;
483             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
484             break;
485         case OUT_P888:
486             face = OUT_P888;
487             LcdMskReg(inf, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(1));
488             break;
489         default:
490             face = screen->face;
491             break;
492     }
493
494      LcdMskReg(inf, DSP_CTRL0,
495         m_DISPLAY_FORMAT | m_HSYNC_POLARITY | m_VSYNC_POLARITY | m_DEN_POLARITY |
496         m_DCLK_POLARITY | m_COLOR_SPACE_CONVERSION,
497         v_DISPLAY_FORMAT(face) | v_HSYNC_POLARITY(screen->pin_hsync) | v_VSYNC_POLARITY(screen->pin_vsync) |
498         v_DEN_POLARITY(screen->pin_den) | v_DCLK_POLARITY(screen->pin_dclk) | v_COLOR_SPACE_CONVERSION(0)
499         );
500
501      LcdMskReg(inf, DSP_CTRL1, m_BG_COLOR,  v_BG_COLOR(0x000000) );
502
503      LcdMskReg(inf, SWAP_CTRL, m_OUTPUT_RB_SWAP | m_OUTPUT_RG_SWAP | m_DELTA_SWAP | m_DUMMY_SWAP,
504             v_OUTPUT_RB_SWAP(screen->swap_rb) | v_OUTPUT_RG_SWAP(screen->swap_rg) | v_DELTA_SWAP(screen->swap_delta) | v_DUMMY_SWAP(screen->swap_dumy));
505
506         // set horizontal & vertical out timing
507         if(SCREEN_MCU==inf->cur_screen->type)
508     {
509             right_margin = x_res/6;
510         }
511
512     printk("screen->hsync_len =%d,  screen->left_margin =%d, x_res =%d,  right_margin = %d \n",
513         screen->hsync_len , screen->left_margin , x_res , right_margin );
514     LcdMskReg(inf, DSP_HTOTAL_HS_END, m_BIT11LO | m_BIT11HI, v_BIT11LO(screen->hsync_len) |
515              v_BIT11HI(screen->hsync_len + screen->left_margin + x_res + right_margin));
516     LcdMskReg(inf, DSP_HACT_ST_END, m_BIT11LO | m_BIT11HI, v_BIT11LO(screen->hsync_len + screen->left_margin + x_res) |
517              v_BIT11HI(screen->hsync_len + screen->left_margin));
518
519     LcdMskReg(inf, DSP_VTOTAL_VS_END, m_BIT11LO | m_BIT11HI, v_BIT11LO(screen->vsync_len) |
520               v_BIT11HI(screen->vsync_len + screen->upper_margin + y_res + lower_margin));
521     LcdMskReg(inf, DSP_VACT_ST_END, m_BIT11LO | m_BIT11HI,  v_BIT11LO(screen->vsync_len + screen->upper_margin+y_res)|
522               v_BIT11HI(screen->vsync_len + screen->upper_margin));
523
524     LcdMskReg(inf, DSP_VS_ST_END_F1, m_BIT11LO | m_BIT11HI, v_BIT11LO(0) | v_BIT11HI(0));
525     LcdMskReg(inf, DSP_VACT_ST_END_F1, m_BIT11LO | m_BIT11HI, v_BIT11LO(0) | v_BIT11HI(0));
526
527         // let above to take effect
528     LcdWrReg(inf, REG_CFG_DONE, 0x01);
529
530     inf->clk = clk_get(&g_pdev->dev, "hclk_lcdc");
531     if (!inf->clk || IS_ERR(inf->clk))
532     {
533         printk(KERN_ERR "failed to get lcdc_hclk source\n");
534         return ;
535     }
536
537     inf->dclk = clk_get(&g_pdev->dev, "dclk_lcdc");
538         if (!inf->dclk || IS_ERR(inf->dclk))
539     {
540                 printk(KERN_ERR "failed to get lcd dclock source\n");
541                 return ;
542         }
543     inf->dclk_divider= clk_get(&g_pdev->dev, "dclk_lcdc_div");
544     if (!inf->dclk_divider || IS_ERR(inf->dclk_divider))
545     {
546                 printk(KERN_ERR "failed to get lcd clock lcdc_divider source \n");
547                 return ;
548         }
549
550     if(inf->cur_screen == &inf->panel1_info)    {
551         inf->dclk_parent = clk_get(&g_pdev->dev, "periph_pll");
552     }    else    {
553         inf->dclk_parent = clk_get(&g_pdev->dev, "codec_pll");
554                 clk_set_rate(inf->dclk_parent, 297000000);
555     }
556
557     if (!inf->dclk_parent || IS_ERR(inf->dclk_parent))
558     {
559                 printk(KERN_ERR "failed to get lcd dclock parent source\n");
560                 return ;
561         }
562
563     inf->aclk = clk_get(&g_pdev->dev, "aclk_lcdc");
564     if (!inf->aclk || IS_ERR(inf->aclk))
565     {
566                 printk(KERN_ERR "failed to get lcd clock clk_share_mem source \n");
567                 return ;
568         }
569     inf->aclk_parent = clk_get(&g_pdev->dev, "periph_pll");
570     if (!inf->dclk_parent || IS_ERR(inf->dclk_parent))
571     {
572                 printk(KERN_ERR "failed to get lcd dclock parent source\n");
573                 return ;
574         }
575
576     // set lcdc clk
577     if(SCREEN_MCU==screen->type)    screen->pixclock = 150000000; //mcu fix to 150 MHz
578
579     if(initscreen == 0)    //not init
580     {
581         clk_disable(inf->dclk);
582         clk_disable(inf->clk);
583         clk_disable(inf->aclk);
584     }
585
586     clk_set_parent(inf->dclk_divider, inf->dclk_parent);
587     clk_set_parent(inf->dclk, inf->dclk_divider);
588     clk_set_parent(inf->aclk, inf->aclk_parent);
589
590     fbprintk(">>>>>> set lcdc dclk need %d HZ, clk_parent = %d hz \n ", screen->pixclock, clk_rate);
591
592     ret = clk_set_rate(inf->dclk_divider, screen->pixclock);
593     if(ret)
594     {
595         printk(KERN_ERR ">>>>>> set lcdc dclk_divider faild \n ");
596     }
597
598     if(screen->lcdc_aclk){
599         aclk_rate = screen->lcdc_aclk;
600     }
601     ret = clk_set_rate(inf->aclk, aclk_rate);
602     if(ret){
603         printk(KERN_ERR ">>>>>> set lcdc dclk_divider faild \n ");
604     }
605
606     clk_enable(inf->dclk);
607     clk_enable(inf->clk);
608     clk_enable(inf->aclk);
609
610     // init screen panel
611     if(screen->init)
612     {
613         screen->init();
614     }
615
616 }
617 #ifdef CONFIG_CPU_FREQ
618 /*
619 * CPU clock speed change handler. We need to adjust the LCD timing
620 * parameters when the CPU clock is adjusted by the power management
621 * subsystem.
622 */
623 #define TO_INF(ptr,member) container_of(ptr,struct rk29fb_inf,member)
624
625 static int
626 rk29fb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
627 {
628     struct rk29fb_inf *inf = TO_INF(nb, freq_transition);
629     struct rk29fb_screen *screen = inf->cur_screen;
630     u32 dclk_rate = 0;
631
632     switch (val)
633     {
634     case CPUFREQ_PRECHANGE:
635           break;
636     case CPUFREQ_POSTCHANGE:
637         {
638          dclk_rate = screen->pixclock * 1000000;
639
640          fbprintk(">>>>>> set lcdc dclk need %d HZ, clk_parent = %d hz \n ", screen->pixclock, dclk_rate);
641
642          clk_set_rate(inf->dclk_divider, dclk_rate);
643          break;
644         }
645     }
646     return 0;
647 }
648 #endif
649
650 static inline unsigned int chan_to_field(unsigned int chan,
651                                          struct fb_bitfield *bf)
652 {
653         chan &= 0xffff;
654         chan >>= 16 - bf->length;
655         return chan << bf->offset;
656 }
657
658 static int fb_setcolreg(unsigned regno,
659                                unsigned red, unsigned green, unsigned blue,
660                                unsigned transp, struct fb_info *info)
661 {
662         unsigned int val;
663 //      fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
664
665         switch (info->fix.visual) {
666         case FB_VISUAL_TRUECOLOR:
667                 /* true-colour, use pseudo-palette */
668                 if (regno < 16) {
669                         u32 *pal = info->pseudo_palette;
670                         val  = chan_to_field(red,   &info->var.red);
671                         val |= chan_to_field(green, &info->var.green);
672                         val |= chan_to_field(blue,  &info->var.blue);
673                         pal[regno] = val;
674                 }
675                 break;
676         default:
677                 return -1;      /* unknown type */
678         }
679
680         return 0;
681 }
682 #if 0
683
684 int rk29_set_cursor(struct fb_info *info, struct fb_cursor *cursor)
685 {
686     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
687
688     //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
689
690     /* check not being asked to exceed capabilities */
691
692     if (cursor->image.width > 32)
693         return -EINVAL;
694
695     if (cursor->image.height > 32)
696         return -EINVAL;
697
698     if (cursor->image.depth > 1)
699         return -EINVAL;
700
701     if (cursor->enable)
702         LcdSetBit(inf, SYS_CONFIG, m_HWC_ENABLE);
703     else
704         LcdClrBit(inf, SYS_CONFIG, m_HWC_ENABLE);
705
706     /* set data */
707     if (cursor->set & FB_CUR_SETPOS)
708     {
709         unsigned int x = cursor->image.dx;
710         unsigned int y = cursor->image.dy;
711
712         if (x >= 0x800 || y >= 0x800 )
713             return -EINVAL;
714         LcdWrReg(inf, HWC_DSP_ST, v_BIT11LO(x)|v_BIT11HI(y));
715     }
716
717
718     if (cursor->set & FB_CUR_SETCMAP)
719     {
720         unsigned int bg_col = cursor->image.bg_color;
721         unsigned int fg_col = cursor->image.fg_color;
722
723         fbprintk("%s: update cmap (%08x,%08x)\n",
724             __func__, bg_col, fg_col);
725
726         LcdMskReg(inf, HWC_COLOR_LUT0, m_HWC_R|m_HWC_G|m_HWC_B,
727                   v_HWC_R(info->cmap.red[bg_col]>>8) | v_HWC_G(info->cmap.green[bg_col]>>8) | v_HWC_B(info->cmap.blue[bg_col]>>8));
728
729         LcdMskReg(inf, HWC_COLOR_LUT2, m_HWC_R|m_HWC_G|m_HWC_B,
730                          v_HWC_R(info->cmap.red[fg_col]>>8) | v_HWC_G(info->cmap.green[fg_col]>>8) | v_HWC_B(info->cmap.blue[fg_col]>>8));
731     }
732
733     if ((cursor->set & FB_CUR_SETSIZE ||
734         cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE))
735         && info->screen_base && info->fix.smem_start && info->fix.smem_len)
736     {
737         /* rk29 cursor is a 2 bpp 32x32 bitmap this routine
738          * clears it to transparent then combines the cursor
739          * shape plane with the colour plane to set the
740          * cursor */
741         int x, y;
742         const unsigned char *pcol = cursor->image.data;
743         const unsigned char *pmsk = cursor->mask;
744         void __iomem   *dst;
745         unsigned long cursor_mem_start;
746         unsigned char  dcol = 0;
747         unsigned char  dmsk = 0;
748         unsigned int   op;
749
750         dst = info->screen_base + info->fix.smem_len - CURSOR_BUF_SIZE;
751             cursor_mem_start = info->fix.smem_start + info->fix.smem_len - CURSOR_BUF_SIZE;
752
753         fbprintk("%s: setting shape (%d,%d)\n",
754             __func__, cursor->image.width, cursor->image.height);
755
756         memset(dst, 0, CURSOR_BUF_SIZE);
757
758         for (y = 0; y < cursor->image.height; y++)
759         {
760             for (x = 0; x < cursor->image.width; x++)
761             {
762                 if ((x % 8) == 0) {
763                     dcol = *pcol++;
764                     dmsk = *pmsk++;
765                 } else {
766                     dcol >>= 1;
767                     dmsk >>= 1;
768                 }
769
770                 if (dmsk & 1) {
771                     op = (dcol & 1) ? 1 : 3;
772                     op <<= ((x % 4) * 2);
773                     *(u8*)(dst+(x/4)) |= op;
774                 }
775             }
776             dst += (32*2)/8;
777         }
778         LcdSetBit(inf, SYS_CONFIG,m_HWC_RELOAD_EN);
779         LcdWrReg(inf, HWC_MST, cursor_mem_start);
780         // flush end when wq_condition=1 in mcu panel, but not in rgb panel
781         if(SCREEN_MCU == inf->cur_screen->type) {
782             wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
783             wq_condition = 0;
784         } else {
785             wq_condition = 0;
786             wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
787         }
788         LcdClrBit(inf, SYS_CONFIG, m_HWC_RELOAD_EN);
789     }
790
791     return 0;
792 }
793 #endif
794
795 static int win0_blank(int blank_mode, struct fb_info *info)
796 {
797     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
798
799     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
800
801         CHK_SUSPEND(inf);
802
803     switch(blank_mode)
804     {
805     case FB_BLANK_UNBLANK:
806         LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(1));
807         break;
808     default:
809         LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(0));
810         break;
811     }
812     LcdWrReg(inf, REG_CFG_DONE, 0x01);
813
814         mcu_refresh(inf);
815     return 0;
816 }
817
818 static int win0_set_par(struct fb_info *info)
819 {
820     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
821     struct rk29fb_screen *screen = inf->cur_screen;
822     struct fb_var_screeninfo *var = &info->var;
823     struct fb_fix_screeninfo *fix = &info->fix;
824     struct win0_par *par = info->par;
825
826         u32 xact = var->xres;                       /* visible resolution               */
827         u32 yact = var->yres;
828         u32 xvir = var->xres_virtual;           /* virtual resolution           */
829         u32 yvir = var->yres_virtual;
830         u32 xact_st = var->xoffset;                     /* offset from virtual to visible */
831         u32 yact_st = var->yoffset;                     /* resolution                   */
832     u32 xpos = par->xpos;
833     u32 ypos = par->ypos;
834
835     u32 ScaleYrgbX=0x1000,ScaleYrgbY=0x1000;
836     u32 ScaleCbrX=0x1000, ScaleCbrY=0x1000;
837
838     u8 data_format = var->nonstd&0x0f;
839     u32 y_addr = 0;       //user alloc buf addr y
840     u32 uv_addr = 0;
841
842     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
843
844         CHK_SUSPEND(inf);
845
846         // calculate the display phy address
847     y_addr = fix->smem_start + par->y_offset;
848     uv_addr = fix->mmio_start + par->uv_offset;
849
850     ScaleYrgbX = CalScaleW0(xact, par->xsize);
851     ScaleYrgbY = CalScaleW0(yact, par->ysize);
852
853     switch (data_format)
854     {
855        case 1:// yuv422
856            ScaleCbrX= CalScaleW0((xact/2), par->xsize);
857            ScaleCbrY =  CalScaleW0(yact, par->ysize);
858            break;
859        case 2: // yuv4200
860        case 3: // yuv4201
861            ScaleCbrX= CalScaleW0(xact/2, par->xsize);
862            ScaleCbrY =  CalScaleW0(yact/2, par->ysize);
863            break;
864        case 4: // none
865        case 5:// yuv444
866            ScaleCbrX= CalScaleW0(xact, par->xsize);
867            ScaleCbrY =  CalScaleW0(yact, par->ysize);
868            break;
869        default:
870            break;
871     }
872
873     xpos += (screen->left_margin + screen->hsync_len);
874     ypos += (screen->upper_margin + screen->vsync_len);
875
876     LcdWrReg(inf, WIN0_YRGB_MST, y_addr);
877     LcdWrReg(inf, WIN0_CBR_MST, uv_addr);
878
879     LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE | m_W0_FORMAT, v_W0_ENABLE(par->addr_seted) | v_W0_FORMAT(par->format));
880
881     LcdMskReg(inf, WIN0_VIR, m_WORDLO | m_WORDHI, v_VIRWIDTH(xvir) | v_VIRHEIGHT((yvir)) );
882     LcdMskReg(inf, WIN0_ACT_INFO, m_WORDLO | m_WORDHI, v_WORDLO(xact) | v_WORDHI(yact));
883     LcdMskReg(inf, WIN0_DSP_ST, m_BIT11LO | m_BIT11HI, v_BIT11LO(xpos) | v_BIT11HI(ypos));
884     LcdMskReg(inf, WIN0_DSP_INFO, m_BIT11LO | m_BIT11HI,  v_BIT11LO(par->xsize) | v_BIT11HI(par->ysize));
885     LcdMskReg(inf, WIN0_SCL_FACTOR_YRGB, m_WORDLO | m_WORDHI, v_WORDLO(ScaleYrgbX) | v_WORDHI(ScaleYrgbY));
886     LcdMskReg(inf, WIN0_SCL_FACTOR_CBR, m_WORDLO | m_WORDHI, v_WORDLO(ScaleCbrX) | v_WORDHI(ScaleCbrY));
887
888     switch(par->format)
889     {
890     case 0:  //rgb888
891         LcdMskReg(inf, SWAP_CTRL, m_W0_YRGB_8_SWAP | m_W0_YRGB_16_SWAP | m_W0_YRGB_R_SHIFT_SWAP | m_W0_565_RB_SWAP | m_W0_YRGB_M8_SWAP | m_W0_CBR_8_SWAP,
892             v_W0_YRGB_8_SWAP(1) | v_W0_YRGB_16_SWAP(1) | v_W0_YRGB_R_SHIFT_SWAP(1) | v_W0_565_RB_SWAP(1) | v_W0_YRGB_M8_SWAP(0) | v_W0_CBR_8_SWAP(0));
893     case 1:  //rgb565
894         LcdMskReg(inf, SWAP_CTRL, m_W0_YRGB_8_SWAP | m_W0_YRGB_16_SWAP | m_W0_YRGB_R_SHIFT_SWAP | m_W0_565_RB_SWAP | m_W0_YRGB_M8_SWAP | m_W0_CBR_8_SWAP,
895             v_W0_YRGB_8_SWAP(0) | v_W0_YRGB_16_SWAP(0) | v_W0_YRGB_R_SHIFT_SWAP(0) | v_W0_565_RB_SWAP(0) | v_W0_YRGB_M8_SWAP(0) | v_W0_CBR_8_SWAP(0));
896         break;
897     case 4:   //yuv4201
898         LcdMskReg(inf, SWAP_CTRL, m_W0_YRGB_8_SWAP | m_W0_YRGB_16_SWAP | m_W0_YRGB_R_SHIFT_SWAP | m_W0_565_RB_SWAP | m_W0_YRGB_M8_SWAP | m_W0_CBR_8_SWAP,
899             v_W0_YRGB_8_SWAP(0) | v_W0_YRGB_16_SWAP(0) | v_W0_YRGB_R_SHIFT_SWAP(0) | v_W0_565_RB_SWAP(0) |
900             v_W0_YRGB_M8_SWAP((var->rotate==0)) | v_W0_CBR_8_SWAP(0));
901         break;
902     default:
903         LcdMskReg(inf, SWAP_CTRL, m_W0_YRGB_8_SWAP | m_W0_YRGB_16_SWAP | m_W0_YRGB_R_SHIFT_SWAP | m_W0_565_RB_SWAP | m_W0_YRGB_M8_SWAP | m_W0_CBR_8_SWAP,
904             v_W0_YRGB_8_SWAP(0) | v_W0_YRGB_16_SWAP(0) | v_W0_YRGB_R_SHIFT_SWAP(0) | v_W0_565_RB_SWAP(0) | v_W0_YRGB_M8_SWAP(0) | v_W0_CBR_8_SWAP(0) );
905     }
906
907     LcdWrReg(inf, REG_CFG_DONE, 0x01);
908
909     return 0;
910
911 }
912
913 static int win0_pan( struct fb_info *info )
914 {
915     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
916    // struct fb_var_screeninfo *var0 = &info->var;
917     struct fb_fix_screeninfo *fix0 = &info->fix;
918     struct win0_par *par = info->par;
919     u32 y_addr=0, uv_addr=0;
920
921     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
922
923         CHK_SUSPEND(inf);
924
925     y_addr = fix0->smem_start +  par->y_offset;//y_offset;
926     uv_addr = fix0->mmio_start + par->uv_offset ;//uv_offset;
927
928     LcdWrReg(inf, WIN0_YRGB_MST, y_addr);
929     LcdWrReg(inf, WIN0_CBR_MST, uv_addr);
930     LcdWrReg(inf, REG_CFG_DONE, 0x01);
931
932      // enable win0 after the win0 addr is seted
933         LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE((1==par->addr_seted)?(1):(0)));
934         mcu_refresh(inf);
935
936     return 0;
937 }
938
939 static int win1_blank(int blank_mode, struct fb_info *info)
940 {
941     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
942
943     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
944
945         CHK_SUSPEND(inf);
946
947         switch(blank_mode)
948     {
949     case FB_BLANK_UNBLANK:
950         LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(1));
951         break;
952     default:
953         LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0));
954         break;
955     }
956     LcdWrReg(inf, REG_CFG_DONE, 0x01);
957
958         mcu_refresh(inf);
959     return 0;
960 }
961
962 static int win1_set_par(struct fb_info *info)
963 {
964     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
965     struct fb_var_screeninfo *var = &info->var;
966     struct fb_fix_screeninfo *fix = &info->fix;
967     struct rk29fb_screen *screen = inf->cur_screen;
968     struct win0_par *par = info->par;
969
970     u32 offset=0, addr=0, map_size=0, smem_len=0;
971
972     u16 xres_virtual = var->xres_virtual;      //virtual screen size
973
974     u16 xpos_virtual = var->xoffset;           //visiable offset in virtual screen
975     u16 ypos_virtual = var->yoffset;
976
977     u16 xpos = par->xpos;                 //visiable offset in panel
978     u16 ypos = par->ypos;
979
980     u8 trspmode = TRSP_CLOSE;
981     u8 trspval = 0;
982
983     //fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
984
985     addr = fix->smem_start + par->y_offset;
986
987     LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE|m_W1_FORMAT, v_W1_ENABLE(1)|v_W1_FORMAT(par->format));
988
989     xpos += (screen->left_margin + screen->hsync_len);
990     ypos += (screen->upper_margin + screen->vsync_len);
991
992     LcdWrReg(inf, WIN1_YRGB_MST, addr);
993
994     LcdMskReg(inf, WIN1_DSP_ST, m_BIT11LO|m_BIT11HI, v_BIT11LO(xpos) | v_BIT11HI(ypos));
995     LcdMskReg(inf, WIN1_DSP_INFO, m_BIT11LO|m_BIT11HI, v_BIT11LO(par->xsize) | v_BIT11HI(par->ysize));
996
997     LcdMskReg(inf, WIN1_VIR, m_WORDLO , v_WORDLO(xres_virtual));
998
999     LcdMskReg(inf, BLEND_CTRL, m_W1_BLEND_EN |  m_W1_BLEND_FACTOR,
1000         v_W1_BLEND_EN((TRSP_FMREG==trspmode) || (TRSP_MASK==trspmode)) | v_W1_BLEND_FACTOR(trspval));
1001
1002      // enable win1 color key and set the color to black(rgb=0)
1003     LcdMskReg(inf, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR, v_COLORKEY_EN(1) | v_KEYCOLOR(0));
1004
1005     if(1==par->format) //rgb565
1006     {
1007         LcdMskReg(inf, SWAP_CTRL, m_W1_8_SWAP | m_W1_16_SWAP | m_W1_R_SHIFT_SWAP | m_W1_565_RB_SWAP,
1008             v_W1_8_SWAP(0) | v_W1_16_SWAP(0) | v_W1_R_SHIFT_SWAP(0) | v_W1_565_RB_SWAP(0) );
1009     }
1010     else
1011     {
1012          LcdMskReg(inf, SWAP_CTRL, m_W1_8_SWAP | m_W1_16_SWAP | m_W1_R_SHIFT_SWAP | m_W1_565_RB_SWAP,
1013                 v_W1_8_SWAP(1) | v_W1_16_SWAP(1) | v_W1_R_SHIFT_SWAP(1) | v_W1_565_RB_SWAP(0) );
1014
1015          LcdMskReg(inf, DSP_CTRL0, m_W1_TRANSP_FROM, v_W1_TRANSP_FROM(TRSP_FMRAM==trspmode) );
1016     }
1017
1018         LcdWrReg(inf, REG_CFG_DONE, 0x01);
1019
1020     return 0;
1021 }
1022
1023 static int win1_pan( struct fb_info *info )
1024 {
1025     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1026     struct fb_var_screeninfo *var1 = &info->var;
1027     struct fb_fix_screeninfo *fix1 = &info->fix;
1028     struct win0_par *par = info->par;
1029
1030     u32 addr = 0;
1031
1032         //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1033
1034         CHK_SUSPEND(inf);
1035
1036     addr = fix1->smem_start + par->y_offset;
1037
1038     //fbprintk("info->screen_base = %8x ; fix1->smem_len = %d , addr = %8x\n",(u32)info->screen_base, fix1->smem_len, addr);
1039
1040     LcdWrReg(inf, WIN1_YRGB_MST, addr);
1041     LcdWrReg(inf, REG_CFG_DONE, 0x01);
1042         mcu_refresh(inf);
1043
1044     return 0;
1045 }
1046
1047 static int fb0_blank(int blank_mode, struct fb_info *info)
1048 {
1049         struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1050
1051     if(inf->video_mode == 1)
1052     {
1053         win1_blank(blank_mode, info);
1054     }
1055     else
1056     {
1057         win0_blank(blank_mode, info);
1058     }
1059     return 0;
1060 }
1061
1062 static int fb0_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1063 {
1064     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1065     struct rk29fb_screen *screen = inf->cur_screen;
1066     u16 xpos = (var->nonstd>>8) & 0xfff;
1067     u16 ypos = (var->nonstd>>20) & 0xfff;
1068     u16 xlcd = screen->x_res;
1069     u16 ylcd = screen->y_res;
1070
1071     //fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1072
1073         CHK_SUSPEND(inf);
1074
1075     if( 0==var->xres_virtual || 0==var->yres_virtual ||
1076         0==var->xres || 0==var->yres || var->xres<16 ||
1077         ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) )
1078     {
1079         printk(">>>>>> win1fb_check_var fail 1!!! \n");
1080         printk(">>>>>> 0==%d || 0==%d ", var->xres_virtual,var->yres_virtual);
1081         printk("0==%d || 0==%d || %d<16 || ", var->xres,var->yres,var->xres<16);
1082         printk("bits_per_pixel=%d \n", var->bits_per_pixel);
1083         return -EINVAL;
1084     }
1085
1086     if( (var->xoffset+var->xres)>var->xres_virtual ||
1087         (var->yoffset+var->yres)>var->yres_virtual )
1088     {
1089         printk(">>>>>> win1fb_check_var fail 2!!! \n");
1090         printk(">>>>>> (%d+%d)>%d || ", var->xoffset,var->xres,var->xres_virtual);
1091         printk("(%d+%d)>%d || ", var->yoffset,var->yres,var->yres_virtual);
1092         printk("(%d+%d)>%d || (%d+%d)>%d \n", xpos,var->xres,xlcd,ypos,var->yres,ylcd);
1093         return -EINVAL;
1094     }
1095
1096     switch(var->bits_per_pixel)
1097     {
1098     case 16:    // rgb565
1099         var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1);
1100         var->xres = (var->xres + 0x1) & (~0x1);
1101         var->xoffset = (var->xoffset) & (~0x1);
1102         break;
1103     default:    // rgb888
1104         var->bits_per_pixel = 32;
1105         break;
1106     }
1107
1108     return 0;
1109 }
1110
1111
1112 static int fb0_set_par(struct fb_info *info)
1113 {
1114     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1115     struct fb_var_screeninfo *var = &info->var;
1116     struct fb_fix_screeninfo *fix = &info->fix;
1117     struct rk29fb_screen *screen = inf->cur_screen;
1118     struct win0_par *par = info->par;
1119
1120     u8 format = 0;
1121     u32 offset=0, addr=0, map_size=0, smem_len=0;
1122
1123     u16 xres_virtual = var->xres_virtual;      //virtual screen size
1124
1125     u16 xpos_virtual = var->xoffset;           //visiable offset in virtual screen
1126     u16 ypos_virtual = var->yoffset;
1127
1128     u16 xpos = (screen->x_res - var->xres)/2;                 //visiable offset in panel
1129     u16 ypos = (screen->y_res - var->yres)/2;
1130     u16 xsize = screen->x_res;    //visiable size in panel
1131     u16 ysize = screen->y_res;
1132     u8 trspmode = TRSP_CLOSE;
1133     u8 trspval = 0;
1134
1135     //fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1136
1137         CHK_SUSPEND(inf);
1138
1139     switch(var->bits_per_pixel)
1140     {
1141     case 16:    // rgb565
1142         par->format = 1;
1143         fix->line_length = 2 * xres_virtual;
1144         offset = (ypos_virtual*xres_virtual + xpos_virtual)*2;
1145         break;
1146     case 32:    // rgb888
1147     default:
1148         par->format = 0;
1149         fix->line_length = 4 * xres_virtual;
1150         offset = (ypos_virtual*xres_virtual + xpos_virtual)*4;
1151         break;
1152     }
1153
1154     smem_len = fix->line_length * var->yres_virtual;
1155     map_size = PAGE_ALIGN(smem_len);
1156
1157     if (smem_len > fix->smem_len)     // buffer need realloc
1158     {
1159         printk("%s sorry!!! win1 buf is not enough\n",__FUNCTION__);
1160     }
1161
1162     par->y_offset = offset;
1163     par->addr_seted = 1;
1164
1165     if(inf->video_mode == 1)
1166     {
1167         par->xpos = (screen->x_res - var->xres)/2;              //visiable offset in panel
1168         par->ypos = (screen->y_res - var->yres)/2;
1169         par->xsize = screen->x_res;                            //visiable size in panel
1170         par->ysize = screen->y_res;
1171         win1_set_par(info);
1172     }
1173     else
1174     {
1175         par->xpos = 0;
1176         par->ypos = 0;
1177         par->xsize = screen->x_res;
1178         par->ysize = screen->y_res;
1179         win0_set_par(info);
1180     }
1181
1182     return 0;
1183 }
1184
1185 static int fb0_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1186 {
1187     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1188     struct fb_var_screeninfo *var1 = &info->var;
1189     struct fb_fix_screeninfo *fix1 = &info->fix;
1190     struct win0_par *par = info->par;
1191
1192     u32 offset = 0;
1193
1194         //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1195
1196         CHK_SUSPEND(inf);
1197
1198     switch(var1->bits_per_pixel)
1199     {
1200     case 16:    // rgb565
1201         var->xoffset = (var->xoffset) & (~0x1);
1202         offset = (var->yoffset*var1->xres_virtual + var->xoffset)*2;
1203         break;
1204     case 32:    // rgb888
1205         offset = (var->yoffset*var1->xres_virtual + var->xoffset)*4;
1206         break;
1207     default:
1208         return -EINVAL;
1209     }
1210
1211     par->y_offset = offset;
1212
1213     if(inf->video_mode == 1)
1214     {
1215         win1_pan(info);
1216     }
1217     else
1218     {
1219         win0_pan(info);
1220     }
1221         // flush end when wq_condition=1 in mcu panel, but not in rgb panel
1222     if(SCREEN_MCU == inf->cur_screen->type) {
1223         wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
1224         wq_condition = 0;
1225     } else {
1226         wq_condition = 0;
1227         wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
1228     }
1229     return 0;
1230 }
1231
1232 static int fb0_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
1233 {
1234     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1235         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1236
1237         CHK_SUSPEND(inf);
1238
1239     switch(cmd)
1240     {
1241     case FB0_IOCTL_STOP_TIMER_FLUSH:    //stop timer flush mcu panel after android is runing
1242         if(1==arg)
1243         {
1244             inf->mcu_usetimer = 0;
1245         }
1246         break;
1247    default:
1248         break;
1249     }
1250     return 0;
1251 }
1252
1253 static int fb1_blank(int blank_mode, struct fb_info *info)
1254 {
1255     win0_blank(blank_mode, info);
1256     return 0;
1257 }
1258
1259 static int fb1_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1260 {
1261     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1262     struct rk29fb_screen *screen = inf->cur_screen;
1263
1264     u32 ScaleYRGBY=0x1000;
1265     u16 xpos = (var->nonstd>>8) & 0xfff;   //offset in panel
1266     u16 ypos = (var->nonstd>>20) & 0xfff;
1267     u16 xsize = (var->grayscale>>8) & 0xfff;   //visiable size in panel
1268     u16 ysize = (var->grayscale>>20) & 0xfff;
1269     u16 xlcd = screen->x_res;        //size of panel
1270     u16 ylcd = screen->y_res;
1271     u16 yres = 0;
1272
1273     xpos = (xpos * screen->x_res) / inf->panel1_info.x_res;
1274     ypos = (ypos * screen->y_res) / inf->panel1_info.y_res;
1275     xsize = (xsize * screen->x_res) / inf->panel1_info.x_res;
1276     ysize = (ysize * screen->y_res) / inf->panel1_info.y_res;
1277
1278     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1279
1280         CHK_SUSPEND(inf);
1281
1282     if( 0==var->xres_virtual || 0==var->yres_virtual ||
1283         0==var->xres || 0==var->yres || var->xres<16 ||
1284         0==xsize || 0==ysize || xsize<16 ||
1285         ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) )
1286     {
1287         printk(">>>>>> win0fb_check_var fail 1!!! \n");
1288                 printk("0==%d || 0==%d || 0==%d || 0==%d || %d<16 \n ||0==%d || 0==%d || %d<16 ||((16!=%d)&&(32!=%d)) \n",
1289                                 var->xres_virtual, var->yres_virtual, var->xres, var->yres, var->xres, xsize, ysize, xsize,
1290                         var->bits_per_pixel, var->bits_per_pixel);
1291         return -EINVAL;
1292     }
1293
1294     if( (var->xoffset+var->xres)>var->xres_virtual ||
1295         (var->yoffset+var->yres)>var->yres_virtual ||
1296         (xpos+xsize)>xlcd || (ypos+ysize)>ylcd  )
1297     {
1298         printk(">>>>>> win0fb_check_var fail 2!!! \n");
1299                 printk("(%d+%d)>%d || (%d+%d)>%d || (%d+%d)>%d || (%d+%d)>%d \n ",
1300                                 var->xoffset, var->xres, var->xres_virtual, var->yoffset, var->yres,
1301                                 var->yres_virtual, xpos, xsize, xlcd, ypos, ysize, ylcd);
1302         return -EINVAL;
1303     }
1304
1305     switch(var->nonstd&0x0f)
1306     {
1307     case 0: // rgb
1308         switch(var->bits_per_pixel)
1309         {
1310         case 16:    // rgb565
1311             var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1);
1312             var->xres = (var->xres + 0x1) & (~0x1);
1313             var->xoffset = (var->xoffset) & (~0x1);
1314             break;
1315         default:    // rgb888
1316             var->bits_per_pixel = 32;
1317             break;
1318         }
1319         var->nonstd &= ~0xc0;  //not support I2P in this format
1320         break;
1321     case 1: // yuv422
1322         var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
1323         var->xres = (var->xres + 0x3) & (~0x3);
1324         var->xoffset = (var->xoffset) & (~0x3);
1325         break;
1326     case 2: // yuv4200
1327         var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
1328         var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1);
1329         var->xres = (var->xres + 0x3) & (~0x3);
1330         var->yres = (var->yres + 0x1) & (~0x1);
1331         var->xoffset = (var->xoffset) & (~0x3);
1332         var->yoffset = (var->yoffset) & (~0x1);
1333         break;
1334     case 3: // yuv4201
1335         var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
1336         var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1);
1337         var->xres = (var->xres + 0x3) & (~0x3);
1338         var->yres = (var->yres + 0x1) & (~0x1);
1339         var->xoffset = (var->xoffset) & (~0x3);
1340         var->yoffset = (var->yoffset) & (~0x1);
1341         var->nonstd &= ~0xc0;   //not support I2P in this format
1342         break;
1343     case 4: // none
1344     case 5: // yuv444
1345         var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
1346         var->xres = (var->xres + 0x3) & (~0x3);
1347         var->xoffset = (var->xoffset) & (~0x3);
1348         var->nonstd &= ~0xc0;   //not support I2P in this format
1349         break;
1350     default:
1351         printk(">>>>>> fb1 var->nonstd=%d is invalid! \n", var->nonstd);
1352         return -EINVAL;
1353     }
1354
1355     yres = var->yres;
1356
1357     ScaleYRGBY = CalScaleW0(yres, ysize);
1358
1359     if((ScaleYRGBY>0x8000) || (ScaleYRGBY<0x200))
1360     {
1361         return -EINVAL;        // multiple of scale down or scale up can't exceed 8
1362     }
1363
1364     return 0;
1365 }
1366
1367 static int fb1_set_par(struct fb_info *info)
1368 {
1369     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1370     struct rk29fb_screen *screen = inf->cur_screen;
1371     struct fb_var_screeninfo *var = &info->var;
1372     struct fb_fix_screeninfo *fix = &info->fix;
1373     struct win0_par *par = info->par;
1374
1375     u8 format = 0;
1376     u32 cblen=0, crlen=0, map_size=0, smem_len=0;
1377
1378         u32 xact = var->xres;                       /* visible resolution               */
1379         u32 yact = var->yres;
1380         u32 xvir = var->xres_virtual;           /* virtual resolution           */
1381         u32 yvir = var->yres_virtual;
1382         u32 xact_st = var->xoffset;                     /* offset from virtual to visible */
1383         u32 yact_st = var->yoffset;                     /* resolution                   */
1384
1385     u16 xpos = (var->nonstd>>8) & 0xfff;      //visiable pos in panel
1386     u16 ypos = (var->nonstd>>20) & 0xfff;
1387     u16 xsize = (var->grayscale>>8) & 0xfff;  //visiable size in panel
1388     u16 ysize = (var->grayscale>>20) & 0xfff;
1389
1390     u32 ScaleYrgbX=0x1000,ScaleYrgbY=0x1000;
1391     u32 ScaleCbrX=0x1000, ScaleCbrY=0x1000;
1392
1393     u8 data_format = var->nonstd&0x0f;
1394     u32 win0_en = var->reserved[2];
1395     u32 y_addr = var->reserved[3];       //user alloc buf addr y
1396     u32 uv_addr = var->reserved[4];
1397
1398     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1399
1400         CHK_SUSPEND(inf);
1401
1402     xpos = (xpos * screen->x_res) / inf->panel1_info.x_res;
1403     ypos = (ypos * screen->y_res) / inf->panel1_info.y_res;
1404     xsize = (xsize * screen->x_res) / inf->panel1_info.x_res;
1405     ysize = (ysize * screen->y_res) / inf->panel1_info.y_res;
1406
1407         /* calculate y_offset,uv_offset,line_length,cblen and crlen  */
1408     switch (data_format)
1409     {
1410     case 0: // rgb
1411         switch(var->bits_per_pixel)
1412         {
1413         case 16:    // rgb565
1414             format = 1;
1415             fix->line_length = 2 * xvir;
1416             par->y_offset = (yact_st*xvir + xact_st)*2;
1417             break;
1418         case 32:    // rgb888
1419             format = 0;
1420             fix->line_length = 4 * xvir;
1421             par->y_offset = (yact_st*xvir + xact_st)*4;
1422             break;
1423         default:
1424             return -EINVAL;
1425         }
1426         break;
1427     case 1: // yuv422
1428         format = 2;
1429         fix->line_length = xvir;
1430         cblen = crlen = (xvir*yvir)/2;
1431         par->y_offset = yact_st*xvir + xact_st;
1432         par->uv_offset = yact_st*xvir + xact_st;
1433         break;
1434     case 2: // yuv4200
1435         format = 3;
1436         fix->line_length = xvir;
1437         cblen = crlen = (xvir*yvir)/4;
1438
1439         par->y_offset = yact_st*xvir + xact_st;
1440         par->uv_offset = (yact_st/2)*xvir + xact_st;
1441
1442         break;
1443     case 3: // yuv4201
1444         format = 4;
1445         fix->line_length = xvir;
1446         par->y_offset = (yact_st/2)*2*xvir + (xact_st)*2;
1447         par->uv_offset = (yact_st/2)*xvir + xact_st;
1448         cblen = crlen = (xvir*yvir)/4;
1449         break;
1450     case 4: // none
1451     case 5: // yuv444
1452         format = 5;
1453         fix->line_length = xvir;
1454         par->y_offset = yact_st*xvir + xact_st;
1455         par->uv_offset = yact_st*2*xvir + xact_st*2;
1456         cblen = crlen = (xvir*yvir);
1457         break;
1458     default:
1459         return -EINVAL;
1460     }
1461
1462     smem_len = fix->line_length * yvir + cblen + crlen;
1463     map_size = PAGE_ALIGN(smem_len);
1464
1465     fix->smem_start = y_addr;
1466     fix->smem_len = smem_len;
1467     fix->mmio_start = uv_addr;
1468
1469     par->addr_seted = (((-1==(int)y_addr)&&(-1==(int)uv_addr))||((0==(int)y_addr)&&(0==(int)uv_addr))) ? 0 : 1;
1470     fbprintk("buffer alloced by user fix->smem_start = %8x, fix->smem_len = %8x, fix->mmio_start = %8x \n", (u32)fix->smem_start, (u32)fix->smem_len, (u32)fix->mmio_start);
1471
1472     par->format = format;
1473     par->xpos = xpos;
1474     par->ypos = ypos;
1475     par->xsize = xsize;
1476     par->ysize = ysize;
1477     par->addr_seted = (par->addr_seted && win0_en);
1478     win0_set_par(info);
1479
1480     return 0;
1481 }
1482
1483 static int fb1_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1484 {
1485     struct win0_par *par = info->par;
1486      // enable win0 after the win0 addr is seted
1487     par->par_seted = 1;
1488     win0_pan(info);
1489     return 0;
1490 }
1491
1492 int fb1_open(struct fb_info *info, int user)
1493 {
1494     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1495     struct win0_par *par = info->par;
1496
1497     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1498
1499     par->par_seted = 0;
1500     par->addr_seted = 0;
1501     inf->video_mode = 1;
1502
1503     if(par->refcount) {
1504         printk(">>>>>> fb1 has opened! \n");
1505         return -EACCES;
1506     } else {
1507         par->refcount++;
1508         return 0;
1509     }
1510 }
1511
1512 int fb1_release(struct fb_info *info, int user)
1513 {
1514     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1515     struct win0_par *par = info->par;
1516         struct fb_var_screeninfo *var0 = &info->var;
1517
1518     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1519
1520     if(par->refcount) {
1521         par->refcount--;
1522         inf->video_mode = 0;
1523
1524         win1_blank(FB_BLANK_POWERDOWN, info);
1525         // wait for lcdc stop access memory
1526         msleep(50);
1527
1528         // unmap memory
1529         info->screen_base = 0;
1530         info->fix.smem_start = 0;
1531         info->fix.smem_len = 0;
1532                 // clean the var param
1533                 memset(var0, 0, sizeof(struct fb_var_screeninfo));
1534     }
1535
1536     return 0;
1537 }
1538
1539 static int fb1_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
1540 {
1541     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1542     struct win0_par *par = info->par;
1543     void __user *argp = (void __user *)arg;
1544
1545         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1546     fbprintk("win0fb_ioctl cmd = %8x, arg = %8x \n", (u32)cmd, (u32)arg);
1547
1548         CHK_SUSPEND(inf);
1549
1550     switch(cmd)
1551     {
1552     case FB1_IOCTL_GET_PANEL_SIZE:    //get panel size
1553         {
1554             u32 panel_size[2];
1555              if(inf->fb1->var.rotate == 270) {
1556                 panel_size[0] = inf->cur_screen->y_res;
1557                 panel_size[1] = inf->cur_screen->x_res;
1558             } else {
1559                 panel_size[0] = inf->cur_screen->x_res;
1560                 panel_size[1] = inf->cur_screen->y_res;
1561             }
1562
1563             if(copy_to_user(argp, panel_size, 8))  return -EFAULT;
1564         }
1565         break;
1566
1567     case FB1_IOCTL_SET_YUV_ADDR:    //set y&uv address to register direct
1568         {
1569             u32 yuv_phy[2];
1570             if (copy_from_user(yuv_phy, argp, 8))
1571                             return -EFAULT;
1572
1573             yuv_phy[0] += par->y_offset;
1574             yuv_phy[1] += par->uv_offset;
1575
1576             LcdWrReg(inf, WIN0_YRGB_MST, yuv_phy[0]);
1577             LcdWrReg(inf, WIN0_CBR_MST, yuv_phy[1]);
1578             LcdWrReg(inf, REG_CFG_DONE, 0x01);
1579             // enable win0 after the win0 par is seted
1580             par->addr_seted = 1;
1581             if(par->par_seted) {
1582                 LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(1));
1583                 mcu_refresh(inf);
1584             }
1585         }
1586         break;
1587
1588     case FB1_IOCTL_SET_ROTATE:    //change MCU panel scan direction
1589         fbprintk(">>>>>> change lcdc direction(%d) \n", (int)arg);
1590         return -1;
1591         break;
1592     default:
1593         break;
1594     }
1595     return 0;
1596 }
1597
1598 static struct fb_ops fb1_ops = {
1599         .owner          = THIS_MODULE,
1600         .fb_open    = fb1_open,
1601         .fb_release = fb1_release,
1602         .fb_check_var   = fb1_check_var,
1603         .fb_set_par     = fb1_set_par,
1604         .fb_blank       = fb1_blank,
1605     .fb_pan_display = fb1_pan_display,
1606     .fb_ioctl = fb1_ioctl,
1607         .fb_setcolreg   = fb_setcolreg,
1608         .fb_fillrect    = cfb_fillrect,
1609         .fb_copyarea    = cfb_copyarea,
1610         .fb_imageblit   = cfb_imageblit,
1611 };
1612
1613 static struct fb_ops fb0_ops = {
1614         .owner          = THIS_MODULE,
1615         .fb_check_var   = fb0_check_var,
1616         .fb_set_par = fb0_set_par,
1617         .fb_blank   = fb0_blank,
1618         .fb_pan_display = fb0_pan_display,
1619     .fb_ioctl = fb0_ioctl,
1620         .fb_setcolreg   = fb_setcolreg,
1621         .fb_fillrect    = cfb_fillrect,
1622         .fb_copyarea    = cfb_copyarea,
1623         .fb_imageblit   = cfb_imageblit,
1624         //.fb_cursor      = rk29_set_cursor,
1625 };
1626
1627 /*
1628 enable: 1, switch to tv or hdmi; 0, switch to lcd
1629 */
1630 int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable )
1631 {
1632     struct rk29fb_inf *inf = platform_get_drvdata(g_pdev);
1633    // struct rk29fb_info *mach_info = g_pdev->dev.platform_data;
1634
1635     memcpy(&inf->panel2_info, screen, sizeof( struct rk29fb_screen ));
1636
1637     if(enable)inf->cur_screen = &inf->panel2_info;
1638     else inf->cur_screen = &inf->panel1_info;
1639
1640     /* Black out, because some display device need clock to standby */
1641     //LcdMskReg(inf, DSP_CTRL_REG1, m_BLACK_OUT, v_BLACK_OUT(1));
1642    // LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(0));
1643    // LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0));
1644     LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE,  v_BLACK_MODE(1));
1645     LcdWrReg(inf, REG_CFG_DONE, 0x01);
1646     msleep(20);
1647
1648     if(inf->cur_screen->standby)    inf->cur_screen->standby(1);
1649     // operate the display_on pin to power down the lcd
1650     set_lcd_pin(g_pdev, (enable==0));
1651
1652     load_screen(inf->fb0, 0);
1653         mcu_refresh(inf);
1654
1655     fb1_set_par(inf->fb1);
1656     fb0_set_par(inf->fb0);
1657     LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE,  v_BLACK_MODE(0));
1658     LcdWrReg(inf, REG_CFG_DONE, 0x01);
1659
1660     return 0;
1661 }
1662
1663 static irqreturn_t rk29fb_irq(int irq, void *dev_id)
1664 {
1665         struct platform_device *pdev = (struct platform_device*)dev_id;
1666     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
1667     if(!inf)
1668         return IRQ_HANDLED;
1669
1670         //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1671
1672     LcdMskReg(inf, INT_STATUS, m_FRM_STARTCLEAR, v_FRM_STARTCLEAR(1));
1673
1674         if(SCREEN_MCU == inf->cur_screen->type)
1675         {
1676         inf->mcu_isrcnt = !inf->mcu_isrcnt;
1677         if(inf->mcu_isrcnt)
1678             return IRQ_HANDLED;
1679
1680         if(IsMcuUseFmk())
1681         {
1682             if(LcdReadBit(inf, MCU_TIMING_CTRL, m_MCU_HOLD_STATUS) && (inf->mcu_fmksync == 0))
1683             {
1684                 inf->mcu_fmksync = 1;
1685                  if(inf->cur_screen->refresh)
1686                    inf->cur_screen->refresh(REFRESH_END);
1687                 inf->mcu_fmksync = 0;
1688             }
1689             else
1690             {
1691                 return IRQ_HANDLED;
1692             }
1693         }
1694         else
1695         {
1696             if(inf->mcu_needflush) {
1697                 if(inf->cur_screen->refresh)
1698                     inf->cur_screen->refresh(REFRESH_PRE);
1699                 inf->mcu_needflush = 0;
1700                 inf->mcu_isrcnt = 0;
1701                 LcdSetRegBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_FRAME_ST);
1702             } else {
1703                 if(inf->cur_screen->refresh)
1704                     inf->cur_screen->refresh(REFRESH_END);
1705             }
1706         }
1707         }
1708
1709         wq_condition = 1;
1710         wake_up_interruptible(&wq);
1711
1712         return IRQ_HANDLED;
1713 }
1714
1715 #ifdef CONFIG_HAS_EARLYSUSPEND
1716
1717 struct suspend_info {
1718         struct early_suspend early_suspend;
1719         struct rk29fb_inf *inf;
1720 };
1721
1722 void suspend(struct early_suspend *h)
1723 {
1724         struct suspend_info *info = container_of(h, struct suspend_info,
1725                                                 early_suspend);
1726
1727     struct rk29fb_inf *inf = info->inf;
1728
1729     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1730
1731     if(!inf) {
1732         printk("inf==0, rk29fb_suspend fail! \n");
1733         return;
1734     }
1735
1736     set_lcd_pin(g_pdev, 0);
1737
1738         if(inf->cur_screen->standby)
1739         {
1740                 fbprintk(">>>>>> power down the screen! \n");
1741                 inf->cur_screen->standby(1);
1742         }
1743
1744     LcdMskReg(inf, DSP_CTRL1, m_BLANK_MODE , v_BLANK_MODE(1));
1745     LcdMskReg(inf, SYS_CONFIG, m_STANDBY, v_STANDBY(1));
1746         LcdWrReg(inf, REG_CFG_DONE, 0x01);
1747
1748         if(!inf->in_suspend)
1749         {
1750                 fbprintk(">>>>>> diable the lcdc clk! \n");
1751                 msleep(100);
1752         if (inf->dclk){
1753             clk_disable(inf->dclk);
1754         }
1755         if(inf->clk){
1756             clk_disable(inf->clk);
1757         }
1758
1759                 inf->in_suspend = 1;
1760         }
1761
1762 }
1763
1764 void resume(struct early_suspend *h)
1765 {
1766         struct suspend_info *info = container_of(h, struct suspend_info,
1767                                         early_suspend);
1768
1769     struct rk29fb_inf *inf = info->inf;
1770
1771     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1772     if(!inf) {
1773         printk("inf==0, rk29fb_resume fail! \n");
1774         return ;
1775     }
1776
1777         if(inf->in_suspend)
1778         {
1779             inf->in_suspend = 0;
1780         fbprintk(">>>>>> enable the lcdc clk! \n");
1781         if (inf->dclk){
1782             clk_enable(inf->dclk);
1783         }
1784         if(inf->clk){
1785             clk_enable(inf->clk);
1786         }
1787         msleep(100);
1788         }
1789     LcdMskReg(inf, DSP_CTRL1, m_BLANK_MODE , v_BLANK_MODE(0));
1790     LcdMskReg(inf, SYS_CONFIG, m_STANDBY, v_STANDBY(0));
1791     LcdWrReg(inf, REG_CFG_DONE, 0x01);
1792
1793         if(inf->cur_screen->standby)
1794         {
1795                 fbprintk(">>>>>> power on the screen! \n");
1796                 inf->cur_screen->standby(0);
1797         }
1798     msleep(100);
1799     set_lcd_pin(g_pdev, 1);
1800         memcpy((u8*)inf->preg, (u8*)&inf->regbak, 0xa4);  //resume reg
1801 }
1802
1803 struct suspend_info suspend_info = {
1804         .early_suspend.suspend = suspend,
1805         .early_suspend.resume = resume,
1806         .early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
1807 };
1808 #endif
1809
1810 static int __init rk29fb_probe (struct platform_device *pdev)
1811 {
1812     struct rk29fb_inf *inf = NULL;
1813     struct resource *res = NULL;
1814     struct resource *mem = NULL;
1815     struct rk29fb_info *mach_info = NULL;
1816     struct rk29fb_screen *screen = NULL;
1817         int irq = 0;
1818     int ret = 0;
1819
1820     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1821
1822     *(volatile u32 *)(RK29_GRF_BASE+0xac) = ((*(volatile u32 *)(RK29_GRF_BASE+0xac)) & ~0x3FF) | 0x246;
1823
1824     /* Malloc rk29fb_inf and set it to pdev for drvdata */
1825     fbprintk(">> Malloc rk29fb_inf and set it to pdev for drvdata \n");
1826     inf = kmalloc(sizeof(struct rk29fb_inf), GFP_KERNEL);
1827     if(!inf)
1828     {
1829         dev_err(&pdev->dev, ">> inf kmalloc fail!");
1830         ret = -ENOMEM;
1831                 goto release_drvdata;
1832     }
1833     memset(inf, 0, sizeof(struct rk29fb_inf));
1834         platform_set_drvdata(pdev, inf);
1835
1836     mach_info = pdev->dev.platform_data;
1837     /* Fill screen info and set current screen */
1838     fbprintk(">> Fill screen info and set current screen \n");
1839     set_lcd_info(&inf->panel1_info, mach_info->lcd_info);
1840     inf->cur_screen = &inf->panel1_info;
1841     screen = inf->cur_screen;
1842     if(SCREEN_NULL==screen->type)
1843     {
1844         dev_err(&pdev->dev, ">> Please select a display device! \n");
1845         ret = -EINVAL;
1846                 goto release_drvdata;
1847     }
1848
1849     /* get virtual basic address of lcdc register */
1850     fbprintk(">> get virtual basic address of lcdc register \n");
1851     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcdc reg");
1852     if (res == NULL)
1853     {
1854         dev_err(&pdev->dev, "failed to get memory registers\n");
1855         ret = -ENOENT;
1856                 goto release_drvdata;
1857     }
1858     inf->reg_phy_base = res->start;
1859     inf->len = (res->end - res->start) + 1;
1860     mem = request_mem_region(inf->reg_phy_base, inf->len, pdev->name);
1861     if (mem == NULL)
1862     {
1863         dev_err(&pdev->dev, "failed to get memory region\n");
1864         ret = -ENOENT;
1865                 goto release_drvdata;
1866     }
1867     fbprintk("inf->reg_phy_base = 0x%08x, inf->len = %d \n", inf->reg_phy_base, inf->len);
1868     inf->reg_vir_base = ioremap(inf->reg_phy_base, inf->len);
1869     if (inf->reg_vir_base == NULL)
1870     {
1871         dev_err(&pdev->dev, "ioremap() of registers failed\n");
1872         ret = -ENXIO;
1873                 goto release_drvdata;
1874     }
1875     inf->preg = (LCDC_REG*)inf->reg_vir_base;
1876
1877     /* Prepare win1 info */
1878     fbprintk(">> Prepare win1 info \n");
1879         inf->fb0 = framebuffer_alloc(sizeof(struct win0_par), &pdev->dev);
1880     if(!inf->fb0)
1881     {
1882         dev_err(&pdev->dev, ">> fb0 framebuffer_alloc fail!");
1883                 inf->fb0 = NULL;
1884         ret = -ENOMEM;
1885                 goto release_win1fb;
1886     }
1887
1888     strcpy(inf->fb0->fix.id, "fb0");
1889     inf->fb0->fix.type        = FB_TYPE_PACKED_PIXELS;
1890     inf->fb0->fix.type_aux    = 0;
1891     inf->fb0->fix.xpanstep    = 1;
1892     inf->fb0->fix.ypanstep    = 1;
1893     inf->fb0->fix.ywrapstep   = 0;
1894     inf->fb0->fix.accel       = FB_ACCEL_NONE;
1895     inf->fb0->fix.visual      = FB_VISUAL_TRUECOLOR;
1896     inf->fb0->fix.smem_len    = 0;
1897     inf->fb0->fix.line_length = 0;
1898     inf->fb0->fix.smem_start  = 0;
1899
1900     inf->fb0->var.xres = screen->x_res;
1901     inf->fb0->var.yres = screen->y_res;
1902     inf->fb0->var.bits_per_pixel = 16;
1903     inf->fb0->var.xres_virtual = screen->x_res;
1904     inf->fb0->var.yres_virtual = screen->y_res;
1905     inf->fb0->var.width = screen->width;
1906     inf->fb0->var.height = screen->height;
1907     inf->fb0->var.pixclock = screen->pixclock;
1908     inf->fb0->var.left_margin = screen->left_margin;
1909     inf->fb0->var.right_margin = screen->right_margin;
1910     inf->fb0->var.upper_margin = screen->upper_margin;
1911     inf->fb0->var.lower_margin = screen->lower_margin;
1912     inf->fb0->var.vsync_len = screen->vsync_len;
1913     inf->fb0->var.hsync_len = screen->hsync_len;
1914     inf->fb0->var.red    = def_rgb_16.red;
1915     inf->fb0->var.green  = def_rgb_16.green;
1916     inf->fb0->var.blue   = def_rgb_16.blue;
1917     inf->fb0->var.transp = def_rgb_16.transp;
1918
1919     inf->fb0->var.nonstd      = 0;  //win1 format & ypos & xpos (ypos<<20 + xpos<<8 + format)
1920     inf->fb0->var.grayscale   = 0;  //win1 transprent mode & value(mode<<8 + value)
1921     inf->fb0->var.activate    = FB_ACTIVATE_NOW;
1922     inf->fb0->var.accel_flags = 0;
1923     inf->fb0->var.vmode       = FB_VMODE_NONINTERLACED;
1924
1925     inf->fb0->fbops           = &fb0_ops;
1926     inf->fb0->flags           = FBINFO_FLAG_DEFAULT;
1927     inf->fb0->pseudo_palette  = ((struct win0_par*)inf->fb0->par)->pseudo_pal;
1928     inf->fb0->screen_base     = 0;
1929
1930     memset(inf->fb0->par, 0, sizeof(struct win0_par));
1931         ret = fb_alloc_cmap(&inf->fb0->cmap, 256, 0);
1932         if (ret < 0)
1933                 goto release_cmap;
1934
1935     /* alloc win1 buf */
1936     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "win1 buf");
1937     if (res == NULL)
1938     {
1939         dev_err(&pdev->dev, "failed to get win1 memory \n");
1940         ret = -ENOENT;
1941         goto release_win1fb;
1942     }
1943     inf->fb0->fix.smem_start = res->start;
1944     inf->fb0->fix.smem_len = res->end - res->start;
1945     inf->fb0->screen_base = ioremap(res->start, inf->fb0->fix.smem_len);
1946     memset(inf->fb0->screen_base, 0, inf->fb0->fix.smem_len);
1947
1948     /* Prepare win0 info */
1949     fbprintk(">> Prepare win0 info \n");
1950     inf->fb1 = framebuffer_alloc(sizeof(struct win0_par), &pdev->dev);
1951     if(!inf->fb1)
1952     {
1953         dev_err(&pdev->dev, ">> fb1 framebuffer_alloc fail!");
1954                 inf->fb1 = NULL;
1955                 ret = -ENOMEM;
1956                 goto release_win0fb;
1957     }
1958
1959     strcpy(inf->fb1->fix.id, "fb1");
1960         inf->fb1->fix.type            = FB_TYPE_PACKED_PIXELS;
1961         inf->fb1->fix.type_aux    = 0;
1962         inf->fb1->fix.xpanstep    = 1;
1963         inf->fb1->fix.ypanstep    = 1;
1964         inf->fb1->fix.ywrapstep   = 0;
1965         inf->fb1->fix.accel       = FB_ACCEL_NONE;
1966     inf->fb1->fix.visual      = FB_VISUAL_TRUECOLOR;
1967     inf->fb1->fix.smem_len    = 0;
1968     inf->fb1->fix.line_length = 0;
1969     inf->fb1->fix.smem_start  = 0;
1970
1971     inf->fb1->var.xres = screen->x_res;
1972     inf->fb1->var.yres = screen->y_res;
1973     inf->fb1->var.bits_per_pixel = 16;
1974     inf->fb1->var.xres_virtual = screen->x_res;
1975     inf->fb1->var.yres_virtual = screen->y_res;
1976     inf->fb1->var.width = screen->width;
1977     inf->fb1->var.height = screen->height;
1978     inf->fb1->var.pixclock = screen->pixclock;
1979     inf->fb1->var.left_margin = screen->left_margin;
1980     inf->fb1->var.right_margin = screen->right_margin;
1981     inf->fb1->var.upper_margin = screen->upper_margin;
1982     inf->fb1->var.lower_margin = screen->lower_margin;
1983     inf->fb1->var.vsync_len = screen->vsync_len;
1984     inf->fb1->var.hsync_len = screen->hsync_len;
1985     inf->fb1->var.red    = def_rgb_16.red;
1986     inf->fb1->var.green  = def_rgb_16.green;
1987     inf->fb1->var.blue   = def_rgb_16.blue;
1988     inf->fb1->var.transp = def_rgb_16.transp;
1989
1990     inf->fb1->var.nonstd      = 0;  //win0 format & ypos & xpos (ypos<<20 + xpos<<8 + format)
1991     inf->fb1->var.grayscale   = ((inf->fb1->var.yres<<20)&0xfff00000) + ((inf->fb1->var.xres<<8)&0xfff00);//win0 xsize & ysize
1992     inf->fb1->var.activate    = FB_ACTIVATE_NOW;
1993     inf->fb1->var.accel_flags = 0;
1994     inf->fb1->var.vmode       = FB_VMODE_NONINTERLACED;
1995
1996     inf->fb1->fbops           = &fb1_ops;
1997         inf->fb1->flags               = FBINFO_FLAG_DEFAULT;
1998         inf->fb1->pseudo_palette  = ((struct win0_par*)inf->fb1->par)->pseudo_pal;
1999         inf->fb1->screen_base     = 0;
2000
2001     memset(inf->fb1->par, 0, sizeof(struct win0_par));
2002
2003         /* Init all lcdc and lcd before register_framebuffer. */
2004         /* because after register_framebuffer, the win1fb_check_par and winfb_set_par execute immediately */
2005         fbprintk(">> Init all lcdc and lcd before register_framebuffer \n");
2006     init_lcdc(inf->fb0);
2007
2008   #ifdef CONFIG_CPU_FREQ
2009    // inf->freq_transition.notifier_call = rk29fb_freq_transition;
2010    // cpufreq_register_notifier(&inf->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
2011   #endif
2012         fbprintk("got clock\n");
2013
2014         if(mach_info)
2015     {
2016         struct rk29_fb_setting_info fb_setting;
2017         if( OUT_P888==inf->cur_screen->face )     // set lcdc iomux
2018         {
2019             fb_setting.data_num = 24;
2020         }
2021         else if(OUT_P666 == inf->cur_screen->face )
2022         {
2023             fb_setting.data_num = 18;
2024         }
2025         else
2026         {
2027             fb_setting.data_num = 16;
2028         }
2029         fb_setting.den_en = 1;
2030         fb_setting.vsync_en = 1;
2031         fb_setting.disp_on_en = 1;
2032         fb_setting.standby_en = 1;
2033         if( inf->cur_screen->mcu_usefmk )
2034             fb_setting.mcu_fmk_en =1;
2035         mach_info->io_init(&fb_setting);
2036     }
2037
2038         set_lcd_pin(pdev, 1);
2039         mdelay(10);
2040         g_pdev = pdev;
2041         inf->mcu_usetimer = 1;
2042     inf->mcu_fmksync = 0;
2043         load_screen(inf->fb0, 1);
2044
2045     /* Register framebuffer(fb0 & fb1) */
2046     fbprintk(">> Register framebuffer(fb0) \n");
2047     ret = register_framebuffer(inf->fb0);
2048     if(ret<0)
2049     {
2050         printk(">> fb0 register_framebuffer fail!\n");
2051         ret = -EINVAL;
2052                 goto release_win0fb;
2053     }
2054     fbprintk(">> Register framebuffer(fb1) \n");
2055
2056     ret = register_framebuffer(inf->fb1);
2057     if(ret<0)
2058     {
2059         printk(">> fb1 register_framebuffer fail!\n");
2060         ret = -EINVAL;
2061                 goto unregister_win1fb;
2062     }
2063
2064 #ifdef CONFIG_HAS_EARLYSUSPEND
2065         suspend_info.inf = inf;
2066         register_early_suspend(&suspend_info.early_suspend);
2067 #endif
2068
2069     /* get and request irq */
2070     fbprintk(">> get and request irq \n");
2071     irq = platform_get_irq(pdev, 0);
2072     if (irq < 0) {
2073         dev_err(&pdev->dev, "no irq for device\n");
2074         ret = -ENOENT;
2075         goto unregister_win1fb;
2076     }
2077     ret = request_irq(irq, rk29fb_irq, IRQF_DISABLED, pdev->name, pdev);
2078     if (ret) {
2079         dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
2080         ret = -EBUSY;
2081         goto release_irq;
2082     }
2083
2084     if( inf->cur_screen->mcu_usefmk && (mach_info->mcu_fmk_pin != -1) )
2085     {
2086         ret = request_irq(gpio_to_irq(mach_info->mcu_fmk_pin), mcu_irqfmk, GPIOEdgelFalling, pdev->name, pdev);
2087         if (ret)
2088         {
2089             dev_err(&pdev->dev, "cannot get fmk irq %d - err %d\n", irq, ret);
2090             ret = -EBUSY;
2091             goto release_irq;
2092         }
2093     }
2094
2095     printk(" %s ok\n", __FUNCTION__);
2096     return ret;
2097
2098 release_irq:
2099         if(irq>=0)
2100         free_irq(irq, pdev);
2101 unregister_win1fb:
2102     unregister_framebuffer(inf->fb0);
2103 release_win0fb:
2104         if(inf->fb1)
2105                 framebuffer_release(inf->fb1);
2106         inf->fb1 = NULL;
2107 release_cmap:
2108     if(&inf->fb0->cmap)
2109         fb_dealloc_cmap(&inf->fb0->cmap);
2110 release_win1fb:
2111         if(inf->fb0)
2112                 framebuffer_release(inf->fb0);
2113         inf->fb0 = NULL;
2114 release_drvdata:
2115         if(inf && inf->reg_vir_base)
2116         iounmap(inf->reg_vir_base);
2117         if(inf && mem)
2118         release_mem_region(inf->reg_phy_base, inf->len);
2119         if(inf)
2120         kfree(inf);
2121         platform_set_drvdata(pdev, NULL);
2122         return ret;
2123 }
2124
2125 static int rk29fb_remove(struct platform_device *pdev)
2126 {
2127     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
2128     struct fb_info *info = NULL;
2129         //pm_message_t msg;
2130     struct rk29fb_info *mach_info = NULL;
2131     int irq = 0;
2132
2133         fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
2134
2135     if(!inf) {
2136         printk("inf==0, rk29_fb_remove fail! \n");
2137         return -EINVAL;
2138     }
2139
2140     irq = platform_get_irq(pdev, 0);
2141     if (irq >0)
2142     {
2143     free_irq(irq, pdev);
2144     }
2145
2146     mach_info = pdev->dev.platform_data;
2147     if(mach_info->mcu_fmk_pin)
2148     {
2149         free_irq(gpio_to_irq(mach_info->mcu_fmk_pin), pdev);
2150     }
2151
2152         set_lcd_pin(pdev, 0);
2153
2154     // blank the lcdc
2155     if(inf->fb1)
2156         fb1_blank(FB_BLANK_POWERDOWN, inf->fb1);
2157     if(inf->fb0)
2158         fb0_blank(FB_BLANK_POWERDOWN, inf->fb0);
2159
2160         // suspend the lcdc
2161         //rk29fb_suspend(pdev, msg);
2162     // unmap memory and release framebuffer
2163     if(inf->fb1) {
2164         info = inf->fb1;
2165         if (info->screen_base) {
2166                 //dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len),info->screen_base, info->fix.smem_start);
2167                 info->screen_base = 0;
2168                 info->fix.smem_start = 0;
2169                 info->fix.smem_len = 0;
2170         }
2171         unregister_framebuffer(inf->fb1);
2172         framebuffer_release(inf->fb1);
2173         inf->fb1 = NULL;
2174     }
2175     if(inf->fb0) {
2176         info = inf->fb0;
2177         if (info->screen_base) {
2178             //    dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len),info->screen_base, info->fix.smem_start);
2179                 info->screen_base = 0;
2180                 info->fix.smem_start = 0;
2181                 info->fix.smem_len = 0;
2182         }
2183         unregister_framebuffer(inf->fb0);
2184         framebuffer_release(inf->fb0);
2185         inf->fb0 = NULL;
2186     }
2187
2188   #ifdef CONFIG_CPU_FREQ
2189    // cpufreq_unregister_notifier(&inf->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
2190   #endif
2191
2192         if (inf->clk)
2193     {
2194                 clk_disable(inf->clk);
2195                 clk_put(inf->clk);
2196                 inf->clk = NULL;
2197         }
2198     if (inf->dclk)
2199     {
2200                 clk_disable(inf->dclk);
2201                 clk_put(inf->dclk);
2202                 inf->dclk = NULL;
2203         }
2204
2205     kfree(inf);
2206     platform_set_drvdata(pdev, NULL);
2207
2208     return 0;
2209 }
2210
2211 static void rk29fb_shutdown(struct platform_device *pdev)
2212 {
2213     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
2214     mdelay(300);
2215         //printk("----------------------------rk29fb_shutdown----------------------------\n");
2216         set_lcd_pin(pdev, 0);
2217     if (inf->dclk)
2218     {
2219         clk_disable(inf->dclk);
2220     }
2221     if (inf->clk)
2222     {
2223         clk_disable(inf->clk);
2224     }
2225 }
2226
2227 static struct platform_driver rk29fb_driver = {
2228         .probe          = rk29fb_probe,
2229         .remove         = rk29fb_remove,
2230         .driver         = {
2231                 .name   = "rk29-fb",
2232                 .owner  = THIS_MODULE,
2233         },
2234         .shutdown   = rk29fb_shutdown,
2235 };
2236
2237 static int __init rk29fb_init(void)
2238 {
2239     return platform_driver_register(&rk29fb_driver);
2240 }
2241
2242 static void __exit rk29fb_exit(void)
2243 {
2244     platform_driver_unregister(&rk29fb_driver);
2245 }
2246
2247 //subsys_initcall(rk29fb_init);
2248
2249 module_init(rk29fb_init);
2250 module_exit(rk29fb_exit);
2251
2252
2253 MODULE_AUTHOR("  zyw@rock-chips.com");
2254 MODULE_DESCRIPTION("Driver for rk29 fb device");
2255 MODULE_LICENSE("GPL");
2256
2257