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