Merge remote-tracking branch 'kernel-2.6.32/develop' into develop-2.6.36
[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 #include <linux/wakelock.h>
37
38 #include <asm/io.h>
39 #include <asm/div64.h>
40 #include <asm/uaccess.h>
41 #include <asm/cacheflush.h>
42
43 #include "rk29_fb.h"
44
45 #ifdef CONFIG_PM
46 #include <linux/pm.h>
47 #endif
48 #ifdef CONFIG_HDMI
49 #include <linux/completion.h>
50
51 #include <linux/hdmi.h>
52 #endif
53
54 #include <mach/iomux.h>
55 #include <mach/gpio.h>
56 #include <mach/board.h>
57 #include <mach/rk29_iomap.h>
58 #include <mach/pmu.h>
59 #include <mach/rk29-ipp.h>
60 #include <mach/ddr.h>
61
62 #include "./display/screen/screen.h"
63
64 #define ANDROID_USE_THREE_BUFS  0       //android use three buffers to accelerate UI display in rgb plane
65 #define CURSOR_BUF_SIZE         256     //RK2818 cursor need 256B buf
66 int rk29_cursor_buf[CURSOR_BUF_SIZE];
67 char cursor_img[] = {
68 0x00,0x00,0x00,0x00,
69 0x00,0x00,0x00,0x00,
70 0x00,0x00,0x00,0x00,
71 0x00,0x00,0x00,0x00,
72 0x00,0x00,0x00,0x00,
73 0x00,0x20,0x00,0x00,
74 0x00,0x30,0x00,0x00,
75 0x00,0x28,0x00,0x00,
76 0x00,0x24,0x00,0x00,
77 0x00,0x22,0x00,0x00,
78 0x00,0x21,0x00,0x00,
79 0x00,0x20,0x80,0x00,
80 0x00,0x20,0x40,0x00,
81 0x00,0x20,0x20,0x00,
82 0x00,0x20,0x10,0x00,
83 0x00,0x20,0x08,0x00,
84 0x00,0x20,0x7C,0x00,
85 0x00,0x22,0x40,0x00,
86 0x00,0x26,0x40,0x00,
87 0x00,0x29,0x20,0x00,
88 0x00,0x31,0x20,0x00,
89 0x00,0x20,0x90,0x00,
90 0x00,0x00,0x90,0x00,
91 0x00,0x00,0x48,0x00,
92 0x00,0x00,0x48,0x00,
93 0x00,0x00,0x30,0x00,
94 0x00,0x00,0x00,0x00,
95 0x00,0x00,0x00,0x00,
96 0x00,0x00,0x00,0x00,
97 0x00,0x00,0x00,0x00,
98 0x00,0x00,0x00,0x00,
99 0x00,0x00,0x00,0x00
100 };
101
102 #if 0
103         #define fbprintk(msg...)        printk(msg);
104 #else
105         #define fbprintk(msg...)
106 #endif
107
108
109 #if 0
110         #define fbprintk2(msg...)       printk(msg);
111 #else
112         #define fbprintk2(msg...)
113 #endif
114
115 #define LcdReadBit(inf, addr, msk)      ((inf->regbak.addr=inf->preg->addr)&(msk))
116 #define LcdWrReg(inf, addr, val)        inf->preg->addr=inf->regbak.addr=(val)
117 #define LcdRdReg(inf, addr)             (inf->preg->addr)
118 #define LcdSetBit(inf, addr, msk)       inf->preg->addr=((inf->regbak.addr) |= (msk))
119 #define LcdClrBit(inf, addr, msk)       inf->preg->addr=((inf->regbak.addr) &= ~(msk))
120 #define LcdSetRegisterBit(inf, addr, msk)    inf->preg->addr=((inf->preg->addr) |= (msk))
121 #define LcdMskReg(inf, addr, msk, val)  (inf->regbak.addr)&=~(msk);   inf->preg->addr=(inf->regbak.addr|=(val))
122
123
124 #define IsMcuLandscape()                ((SCREEN_MCU==inf->cur_screen->type) && (0==inf->mcu_scandir))
125 #define IsMcuUseFmk()                   ( (2==inf->cur_screen->mcu_usefmk) || (1==inf->cur_screen->mcu_usefmk))
126
127 #define CalScaleW0(x, y)                     (((u32)x*0x1000)/y)
128
129 struct rk29fb_rgb {
130         struct fb_bitfield      red;
131         struct fb_bitfield      green;
132         struct fb_bitfield      blue;
133         struct fb_bitfield      transp;
134 };
135
136 static struct rk29fb_rgb def_rgb_16 = {
137      red:    { offset: 11, length: 5, },
138      green:  { offset: 5,  length: 6, },
139      blue:   { offset: 0,  length: 5, },
140      transp: { offset: 0,  length: 0, },
141 };
142
143 struct win_set {
144         volatile u32 y_offset;
145         volatile u32 c_offset;
146 };
147
148 struct win0_par {
149     u32 refcount;
150     u32 pseudo_pal[16];
151     u32 y_offset;
152     u32 c_offset;
153     u32 xpos;         //size in panel
154     u32 ypos;
155     u32 xsize;        //start point in panel
156     u32 ysize;
157     u32 format;
158
159     wait_queue_head_t wait;
160     struct win_set mirror;
161     struct win_set displ;
162     struct win_set done;
163
164     u8 par_seted;
165     u8 addr_seted;
166 };
167
168 /*
169 struct win1_par {
170         u32 refcount;
171         u32     pseudo_pal[16];
172         int lstblank;
173     u32 xpos;
174     u32 ypos;
175     u32 xsize;
176     u32 ysize;
177     u32 format;
178     u32 addr_offset;
179 };
180 */
181
182 struct rk29fb_inf {
183     struct fb_info *fb1;
184     struct fb_info *fb0;
185
186     void __iomem *reg_vir_base;  // virtual basic address of lcdc register
187         u32 reg_phy_base;       // physical basic address of lcdc register
188         u32 len;               // physical map length of lcdc register
189     u32 video_mode;
190
191     struct clk      *clk;
192     struct clk      *dclk;            //lcdc dclk
193     struct clk      *aclk;   //lcdc share memory frequency
194     struct clk      *aclk_parent;     //lcdc aclk divider frequency source
195     struct clk      *aclk_ddr_lcdc;   //DDR LCDC AXI clock disable.
196     struct clk      *aclk_disp_matrix;  //DISPLAY matrix AXI clock disable.
197     struct clk      *hclk_cpu_display;  //CPU DISPLAY AHB bus clock disable.
198     struct clk      *pd_display;        // display power domain
199     unsigned long       dclk_rate;
200
201     /* lcdc reg base address and backup reg */
202     LCDC_REG *preg;
203     LCDC_REG regbak;
204
205         int in_suspend;
206     int fb0_color_deepth;
207     /* variable used in mcu panel */
208         int mcu_needflush;
209         int mcu_isrcnt;
210         u16 mcu_scandir;
211         struct timer_list mcutimer;
212         int mcu_status;
213         u8 mcu_fmksync;
214         int mcu_usetimer;
215         int mcu_stopflush;
216
217     int setFlag;
218     /* external memery */
219         char __iomem *screen_base2;
220     __u32 smem_len2;
221     unsigned long  smem_start2;
222
223     char __iomem *cursor_base;   /* cursor Virtual address*/
224     __u32 cursor_size;           /* Amount of ioremapped VRAM or 0 */
225     unsigned long  cursor_start;
226
227     struct rk29fb_screen panel1_info;         // 1st panel, it's lcd normally
228     struct rk29fb_screen panel2_info;         // 2nd panel
229     struct rk29fb_screen *cur_screen;
230 #if 0 //def CONFIG_CPU_FREQ
231     struct notifier_block freq_transition;
232 #endif
233
234 };
235
236 typedef enum _TRSP_MODE
237 {
238     TRSP_CLOSE = 0,
239     TRSP_FMREG,
240     TRSP_FMREGEX,
241     TRSP_FMRAM,
242     TRSP_FMRAMEX,
243     TRSP_MASK,
244     TRSP_INVAL
245 } TRSP_MODE;
246
247
248 struct platform_device *g_pdev = NULL;
249 //static int win1fb_set_par(struct fb_info *info);
250
251 #if 0
252 #define CHK_SUSPEND(inf)        \
253         if(inf->in_suspend)     {       \
254                 fbprintk(">>>>>> fb is in suspend! return! \n");        \
255                 return -EPERM;  \
256         }
257 #else
258 #define CHK_SUSPEND(inf)
259 #endif
260
261 static DECLARE_WAIT_QUEUE_HEAD(wq);
262 static int wq_condition = 0;
263 static int wq_condition2 = 0;
264 #if ANDROID_USE_THREE_BUFS
265 static int new_frame_seted = 1;
266 #endif
267 static struct wake_lock idlelock; /* only for fb */
268 #ifdef CONFIG_FB_ROTATE_VIDEO   
269 //add by zyc
270 static bool has_set_rotate; 
271 static u32 last_yuv_phy[2] = {0,0};
272 #endif
273
274 int mcu_do_refresh(struct rk29fb_inf *inf)
275 {
276     if(inf->mcu_stopflush)  return 0;
277
278     if(SCREEN_MCU!=inf->cur_screen->type)   return 0;
279
280     // use frame mark
281     if(IsMcuUseFmk())
282     {
283         inf->mcu_needflush = 1;
284         return 0;
285     }
286
287     // not use frame mark
288     if(LcdReadBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_SELECT))
289     {
290         if(!LcdReadBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_FRAME_ST))
291         {
292             inf->mcu_needflush = 1;
293         }
294         else
295         {
296             if(inf->cur_screen->refresh)    inf->cur_screen->refresh(REFRESH_PRE);
297             inf->mcu_needflush = 0;
298             inf->mcu_isrcnt = 0;
299             LcdSetRegisterBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_FRAME_ST);
300         }
301     }
302     return 0;
303 }
304
305
306 void mcutimer_callback(unsigned long arg)
307 {
308     struct rk29fb_inf *inf = platform_get_drvdata(g_pdev);
309     static int waitcnt = 0;
310
311     mod_timer(&inf->mcutimer, jiffies + HZ/10);
312
313     switch(inf->mcu_status)
314     {
315     case MS_IDLE:
316         inf->mcu_status = MS_MCU;
317         break;
318     case MS_MCU:
319         if(inf->mcu_usetimer)   mcu_do_refresh(inf);
320         break;
321     case MS_EWAITSTART:
322         inf->mcu_status = MS_EWAITEND;
323         waitcnt = 0;
324         break;
325     case MS_EWAITEND:
326         if(0==waitcnt) {
327             mcu_do_refresh(inf);
328         }
329         if(waitcnt++>14) {
330             inf->mcu_status = MS_EEND;
331         }
332         break;
333     case MS_EEND:
334         inf->mcu_status = MS_MCU;
335         break;
336     default:
337         inf->mcu_status = MS_MCU;
338         break;
339     }
340 }
341
342 int mcu_refresh(struct rk29fb_inf *inf)
343 {
344     static int mcutimer_inited = 0;
345
346     if(SCREEN_MCU!=inf->cur_screen->type)   return 0;
347
348     if(!mcutimer_inited)
349     {
350         mcutimer_inited = 1;
351         init_timer(&inf->mcutimer);
352         inf->mcutimer.function = mcutimer_callback;
353         inf->mcutimer.expires = jiffies + HZ/5;
354         inf->mcu_status = MS_IDLE;
355         add_timer(&inf->mcutimer);
356     }
357
358     if(MS_MCU==inf->mcu_status)     mcu_do_refresh(inf);
359
360     return 0;
361 }
362
363 int mcu_ioctl(unsigned int cmd, unsigned long arg)
364 {
365     struct rk29fb_inf *inf = NULL;
366     if(!g_pdev)     return -1;
367
368     inf = dev_get_drvdata(&g_pdev->dev);
369
370     switch(cmd)
371     {
372     case MCU_WRCMD:
373         LcdClrBit(inf, MCU_TIMING_CTRL, m_MCU_RS_SELECT);
374         LcdWrReg(inf, MCU_BYPASS_WPORT, arg);
375         LcdSetBit(inf, MCU_TIMING_CTRL, m_MCU_RS_SELECT);
376         break;
377
378     case MCU_WRDATA:
379         LcdSetBit(inf, MCU_TIMING_CTRL, m_MCU_RS_SELECT);
380         LcdWrReg(inf, MCU_BYPASS_WPORT, arg);
381         break;
382
383     case MCU_SETBYPASS:
384         LcdMskReg(inf, MCU_TIMING_CTRL, m_MCU_BYPASSMODE_SELECT, v_MCU_BYPASSMODE_SELECT(arg));
385         LcdWrReg(inf, REG_CFG_DONE, 0x01);
386         break;
387
388     default:
389         break;
390     }
391
392     return 0;
393 }
394
395 static irqreturn_t mcu_irqfmk(int irq, void *dev_id)
396 {
397         struct platform_device *pdev = (struct platform_device*)dev_id;
398     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
399     struct rk29fb_screen *screen;
400
401     if(!inf)    return IRQ_HANDLED;
402
403     screen = inf->cur_screen;
404
405     if(0==screen->mcu_usefmk) {
406         return IRQ_HANDLED;
407     }
408
409     if(inf->mcu_fmksync == 1)
410         return IRQ_HANDLED;
411
412     inf->mcu_fmksync = 1;
413     if(inf->mcu_needflush)
414     {
415         inf->mcu_needflush = 0;
416         inf->mcu_isrcnt = 0;
417         if(inf->cur_screen->refresh)
418            inf->cur_screen->refresh(REFRESH_PRE);
419         LcdSetBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_FRAME_ST);
420     }
421     inf->mcu_fmksync = 0;
422
423         return IRQ_HANDLED;
424 }
425
426 int init_lcdc(struct fb_info *info)
427 {
428     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
429     u32 msk=0, clr=0;
430
431         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
432
433     inf->clk = clk_get(NULL, "hclk_lcdc");
434     inf->aclk_ddr_lcdc = clk_get(NULL, "aclk_ddr_lcdc");
435     inf->aclk_disp_matrix = clk_get(NULL, "aclk_disp_matrix");
436     inf->hclk_cpu_display = clk_get(NULL, "hclk_cpu_display");
437     inf->pd_display = clk_get(NULL, "pd_display");
438     if ((IS_ERR(inf->clk)) ||
439         (IS_ERR(inf->aclk_ddr_lcdc)) ||
440         (IS_ERR(inf->aclk_disp_matrix)) ||
441         (IS_ERR(inf->hclk_cpu_display)) ||
442         (IS_ERR(inf->pd_display)))
443     {
444         printk(KERN_ERR "failed to get lcdc_hclk source\n");
445         return PTR_ERR(inf->clk);
446     }
447     clk_enable(inf->aclk_disp_matrix);
448     clk_enable(inf->hclk_cpu_display);
449     clk_enable(inf->clk);
450     clk_enable(inf->pd_display);
451     //pmu_set_power_domain(PD_DISPLAY, 1);
452     clk_enable(inf->aclk_ddr_lcdc);
453
454         // set AHB access rule and disable all windows
455     LcdWrReg(inf, SYS_CONFIG, 0x60000000);
456     LcdWrReg(inf, SWAP_CTRL, 0);
457     LcdWrReg(inf, FIFO_WATER_MARK, 0x00000862);//68
458     LcdWrReg(inf, AXI_MS_ID, 0x54321);
459
460         // and mcu holdmode; and set win1 top.
461     LcdMskReg(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_SELECT | m_MCU_HOLDMODE_FRAME_ST | m_MCU_BYPASSMODE_SELECT ,
462             v_MCU_HOLDMODE_SELECT(0)| v_MCU_HOLDMODE_FRAME_ST(0) |v_MCU_BYPASSMODE_SELECT(0));
463
464     // disable blank out, black out, tristate out, yuv2rgb bypass
465     LcdMskReg(inf, BLEND_CTRL,m_W2_BLEND_EN | m_W1_BLEND_EN | m_W0_BLEND_EN | m_HWC_BLEND_EN |
466              m_HWC_BLEND_FACTOR | m_W1_BLEND_FACTOR | m_W0_BLEND_FACTOR,
467              v_W2_BLEND_EN(0) |v_W1_BLEND_EN(0) | v_W0_BLEND_EN(0) | v_HWC_BLEND_EN(0) |
468              v_HWC_BLEND_FACTOR(0) | v_W2_BLEND_FACTOR(0) | v_W1_BLEND_FACTOR(0) | v_W0_BLEND_FACTOR(0)
469              );
470
471     LcdMskReg(inf, WIN0_COLOR_KEY_CTRL, m_COLORKEY_EN, v_COLORKEY_EN(0));
472     LcdMskReg(inf, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN, v_COLORKEY_EN(0));
473
474     LcdWrReg(inf, DSP_CTRL1, 0);
475
476     // initialize all interrupt
477     clr = v_HOR_STARTCLEAR(1) | v_FRM_STARTCLEAR(1) | v_SCANNING_CLEAR(1);
478
479     msk = v_HOR_STARTMASK(1) | v_FRM_STARTMASK(0) | v_SCANNING_MASK(1);
480
481     LcdWrReg(inf, INT_STATUS, clr | msk);
482
483         // let above to take effect
484     LcdWrReg(inf, REG_CFG_DONE, 0x01);
485
486     return 0;
487 }
488
489 void load_screen(struct fb_info *info, bool initscreen)
490 {
491     int ret = -EINVAL;
492     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
493     struct rk29fb_screen *screen = inf->cur_screen;
494     u16 face;
495     u16 mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend;
496     u16 right_margin = screen->right_margin, lower_margin = screen->lower_margin;
497     u16 x_res = screen->x_res, y_res = screen->y_res;
498     u32 aclk_rate = 150000000;
499
500     if(!g_pdev){
501         printk(">>>>>> %s : %s no g_pdev\n", __FILE__, __FUNCTION__);
502         return;
503     }
504
505         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
506
507     // set the rgb or mcu
508     LcdMskReg(inf, MCU_TIMING_CTRL, m_MCU_OUTPUT_SELECT, v_MCU_OUTPUT_SELECT((SCREEN_MCU==screen->type)?(1):(0)));
509
510         // set out format and mcu timing
511     mcu_total  = (screen->mcu_wrperiod*150*1000)/1000000;
512     if(mcu_total>31)    mcu_total = 31;
513     if(mcu_total<3)     mcu_total = 3;
514     mcu_rwstart = (mcu_total+1)/4 - 1;
515     mcu_rwend = ((mcu_total+1)*3)/4 - 1;
516     mcu_csstart = (mcu_rwstart>2) ? (mcu_rwstart-3) : (0);
517     mcu_csend = (mcu_rwend>15) ? (mcu_rwend-1) : (mcu_rwend);
518
519     fbprintk(">> mcu_total=%d, mcu_rwstart=%d, mcu_csstart=%d, mcu_rwend=%d, mcu_csend=%d \n",
520         mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend);
521
522     LcdMskReg(inf, MCU_TIMING_CTRL,
523              m_MCU_CS_ST | m_MCU_CS_END| m_MCU_RW_ST | m_MCU_RW_END |
524              m_MCU_WRITE_PERIOD | m_MCU_HOLDMODE_SELECT | m_MCU_HOLDMODE_FRAME_ST,
525             v_MCU_CS_ST(mcu_csstart) | v_MCU_CS_END(mcu_csend) | v_MCU_RW_ST(mcu_rwstart) |
526             v_MCU_RW_END(mcu_rwend) |  v_MCU_WRITE_PERIOD(mcu_total) |
527             v_MCU_HOLDMODE_SELECT((SCREEN_MCU==screen->type)?(1):(0)) | v_MCU_HOLDMODE_FRAME_ST(0)
528            );
529
530         // set synchronous pin polarity and data pin swap rule
531         switch (screen->face)
532         {
533         case OUT_P565:
534             face = OUT_P565;
535             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
536             break;
537         case OUT_P666:
538             face = OUT_P666;
539             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
540             break;
541         case OUT_D888_P565:
542             face = OUT_P888;
543             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
544             break;
545         case OUT_D888_P666:
546             face = OUT_P888;
547             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
548             break;
549         case OUT_P888:
550             face = OUT_P888;
551             LcdMskReg(inf, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(1));
552             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
553             break;
554         default:
555             LcdMskReg(inf, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(0));
556             LcdMskReg(inf, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
557             face = screen->face;
558             break;
559     }
560
561      LcdMskReg(inf, DSP_CTRL0,
562         m_DISPLAY_FORMAT | m_HSYNC_POLARITY | m_VSYNC_POLARITY | m_DEN_POLARITY |
563         m_DCLK_POLARITY | m_COLOR_SPACE_CONVERSION,
564         v_DISPLAY_FORMAT(face) | v_HSYNC_POLARITY(screen->pin_hsync) | v_VSYNC_POLARITY(screen->pin_vsync) |
565         v_DEN_POLARITY(screen->pin_den) | v_DCLK_POLARITY(screen->pin_dclk) | v_COLOR_SPACE_CONVERSION(0)
566         );
567
568      LcdMskReg(inf, DSP_CTRL1, m_BG_COLOR,  v_BG_COLOR(0x000000) );
569
570      LcdMskReg(inf, SWAP_CTRL, m_OUTPUT_RB_SWAP | m_OUTPUT_RG_SWAP | m_DELTA_SWAP | m_DUMMY_SWAP,
571             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));
572
573         // set horizontal & vertical out timing
574         if(SCREEN_MCU==inf->cur_screen->type)
575     {
576             right_margin = x_res/6;
577         }
578
579     fbprintk("screen->hsync_len =%d,  screen->left_margin =%d, x_res =%d,  right_margin = %d \n",
580         screen->hsync_len , screen->left_margin , x_res , right_margin );
581     LcdMskReg(inf, DSP_HTOTAL_HS_END, m_BIT12LO | m_BIT12HI, v_BIT12LO(screen->hsync_len) |
582              v_BIT12HI(screen->hsync_len + screen->left_margin + x_res + right_margin));
583     LcdMskReg(inf, DSP_HACT_ST_END, m_BIT12LO | m_BIT12HI, v_BIT12LO(screen->hsync_len + screen->left_margin + x_res) |
584              v_BIT12HI(screen->hsync_len + screen->left_margin));
585
586     LcdMskReg(inf, DSP_VTOTAL_VS_END, m_BIT11LO | m_BIT11HI, v_BIT11LO(screen->vsync_len) |
587               v_BIT11HI(screen->vsync_len + screen->upper_margin + y_res + lower_margin));
588     LcdMskReg(inf, DSP_VACT_ST_END, m_BIT11LO | m_BIT11HI,  v_BIT11LO(screen->vsync_len + screen->upper_margin+y_res)|
589               v_BIT11HI(screen->vsync_len + screen->upper_margin));
590
591     LcdMskReg(inf, DSP_VS_ST_END_F1, m_BIT11LO | m_BIT11HI, v_BIT11LO(0) | v_BIT11HI(0));
592     LcdMskReg(inf, DSP_VACT_ST_END_F1, m_BIT11LO | m_BIT11HI, v_BIT11LO(0) | v_BIT11HI(0));
593
594         // let above to take effect
595     LcdWrReg(inf, REG_CFG_DONE, 0x01);
596
597     inf->dclk = clk_get(NULL, "dclk_lcdc");
598     if (IS_ERR(inf->dclk))
599     {
600         printk(KERN_ERR "failed to get lcd dclock source\n");
601         return ;
602     }
603
604     inf->aclk = clk_get(NULL, "aclk_lcdc");
605     if (IS_ERR(inf->aclk))
606     {
607         printk(KERN_ERR "failed to get lcd clock clk_share_mem source \n");
608         return;
609     }
610     inf->aclk_parent = clk_get(NULL, "ddr_pll");//general_pll //ddr_pll
611     if (IS_ERR(inf->aclk_parent))
612     {
613         printk(KERN_ERR "failed to get lcd clock parent source\n");
614         return ;
615     }
616
617     // set lcdc clk
618     if(SCREEN_MCU==screen->type)    screen->pixclock = 150000000; //mcu fix to 150 MHz
619
620     if(initscreen == 0)    //not init
621     {
622         clk_disable(inf->dclk);
623       //  clk_disable(inf->aclk);
624     }
625
626    // clk_disable(inf->aclk_ddr_lcdc);
627    // clk_disable(inf->aclk_disp_matrix);
628    // clk_disable(inf->hclk_cpu_display);
629
630    // clk_disable(inf->clk);
631     
632
633     fbprintk(">>>>>> set lcdc dclk need %d HZ, clk_parent = %d hz ret =%d\n ", screen->pixclock, screen->lcdc_aclk, ret);
634
635     ret = clk_set_rate(inf->dclk, screen->pixclock);
636     if(ret)
637     {
638         printk(KERN_ERR ">>>>>> set lcdc dclk failed\n");
639     }
640     
641     if(initscreen)
642     {
643         ret = clk_set_parent(inf->aclk, inf->aclk_parent);
644         if(screen->lcdc_aclk){
645            aclk_rate = screen->lcdc_aclk;
646         }
647         ret = clk_set_rate(inf->aclk, aclk_rate);
648         if(ret){
649             printk(KERN_ERR ">>>>>> set lcdc aclk failed\n");
650         }
651         clk_enable(inf->aclk);
652     }
653   //  clk_enable(inf->aclk_ddr_lcdc);
654   //  clk_enable(inf->aclk_disp_matrix);
655   //  clk_enable(inf->hclk_cpu_display);       
656   //  clk_enable(inf->clk);
657     clk_enable(inf->dclk);
658
659     // init screen panel
660     if(screen->init)
661     {
662         screen->init();
663     }
664 }
665 #if 0 //def  CONFIG_CPU_FREQ
666 /*
667 * CPU clock speed change handler. We need to adjust the LCD timing
668 * parameters when the CPU clock is adjusted by the power management
669 * subsystem.
670 */
671 #define TO_INF(ptr,member) container_of(ptr,struct rk29fb_inf,member)
672
673 static int
674 rk29fb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
675 {
676     struct rk29fb_inf *inf = TO_INF(nb, freq_transition);
677     struct rk29fb_screen *screen = inf->cur_screen;
678     u32 dclk_rate = 0;
679
680     switch (val)
681     {
682     case CPUFREQ_PRECHANGE:
683           break;
684     case CPUFREQ_POSTCHANGE:
685         {
686          dclk_rate = screen->pixclock * 1000000;
687
688          fbprintk(">>>>>> set lcdc dclk need %d HZ, clk_parent = %d hz \n ", screen->pixclock, dclk_rate);
689
690          clk_set_rate(inf->dclk_divider, dclk_rate);
691          break;
692         }
693     }
694     return 0;
695 }
696 #endif
697
698 static inline unsigned int chan_to_field(unsigned int chan,
699                                          struct fb_bitfield *bf)
700 {
701         chan &= 0xffff;
702         chan >>= 16 - bf->length;
703         return chan << bf->offset;
704 }
705
706 static int fb_setcolreg(unsigned regno,
707                                unsigned red, unsigned green, unsigned blue,
708                                unsigned transp, struct fb_info *info)
709 {
710         unsigned int val;
711 //      fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
712
713         switch (info->fix.visual) {
714         case FB_VISUAL_TRUECOLOR:
715                 /* true-colour, use pseudo-palette */
716                 if (regno < 16) {
717                         u32 *pal = info->pseudo_palette;
718                         val  = chan_to_field(red,   &info->var.red);
719                         val |= chan_to_field(green, &info->var.green);
720                         val |= chan_to_field(blue,  &info->var.blue);
721                         pal[regno] = val;
722                 }
723                 break;
724         default:
725                 return -1;      /* unknown type */
726         }
727
728         return 0;
729 }
730
731 int rk29_set_cursor_en(struct rk29fb_inf *inf, int enable)
732 {
733     if (enable){
734         LcdSetBit(inf, SYS_CONFIG, m_HWC_ENABLE);
735     }else{
736         LcdClrBit(inf, SYS_CONFIG, m_HWC_ENABLE);
737         }
738         LcdWrReg(inf, REG_CFG_DONE, 0x01);
739         return 0;
740 }
741
742 int rk29_set_cursor_pos(struct rk29fb_inf *inf, int x, int y)
743 {
744         struct rk29fb_screen *screen = inf->cur_screen;
745
746     /* set data */
747     if (x >= 0x800 || y >= 0x800 )
748         return -EINVAL;
749         //printk("%s: %08x,%08x \n",__func__, x, y);
750     x += (screen->left_margin + screen->hsync_len);
751     y += (screen->upper_margin + screen->vsync_len);
752     LcdWrReg(inf, HWC_DSP_ST, v_BIT11LO(x)|v_BIT11HI(y));
753         LcdWrReg(inf, REG_CFG_DONE, 0x01);
754     return 0;
755 }
756
757
758 int rk29_set_cursor_colour_map(struct rk29fb_inf *inf, int bg_col, int fg_col)
759 {
760         LcdMskReg(inf, HWC_COLOR_LUT0, m_HWC_R|m_HWC_G|m_HWC_B,bg_col);
761         LcdMskReg(inf, HWC_COLOR_LUT2, m_HWC_R|m_HWC_G|m_HWC_B,fg_col);
762         LcdWrReg(inf, REG_CFG_DONE, 0x01);
763     return 0;
764 }
765
766 #define RK29_CURSOR_WRITE_BIT(addr,mask,value)          (*((char*)addr)) = (((*((char*)addr))&(~((char)mask)))|((char)value))
767 int rk29_set_cursor_img_transform(char *data)
768 {       int x, y;
769         char *pmsk = data;
770         char  *dst = (char*)rk29_cursor_buf;
771         unsigned char  dmsk = 0;
772         unsigned int   op,shift,offset;
773
774         /* rk29 cursor is a 2 bpp 32x32 bitmap this routine
775          * clears it to transparent then combines the cursor
776          * shape plane with the colour plane to set the
777          * cursor */
778         for (y = 0; y < 32; y++)
779         {
780                 for (x = 0; x < 32; x++)
781                 {
782                         if ((x % 8) == 0) {
783                                 dmsk = *pmsk++;
784                         } else {
785                                 dmsk <<= 1;
786                         }
787                         op = (dmsk & 0x80) ? 2 : 3;
788                         shift = (x*2)%8;
789                         offset = x/4;
790                         RK29_CURSOR_WRITE_BIT((dst+offset),(3<<shift),(op<<shift));
791                 }
792                 dst += 8;
793         }
794
795         return 0;
796 }
797
798
799
800 int rk29_set_cursor_img(struct rk29fb_inf *inf, char *data)
801 {
802     if(data)
803     {
804         rk29_set_cursor_img_transform(data);
805     }
806     else
807     {
808         rk29_set_cursor_img_transform(cursor_img);
809     }
810     LcdWrReg(inf, HWC_MST, __pa(rk29_cursor_buf));
811     //LcdSetBit(inf, SYS_CONFIG,m_HWC_RELOAD_EN);
812     LcdSetBit(inf, SYS_CONFIG, m_HWC_RELOAD_EN);
813     flush_cache_all();
814     LcdWrReg(inf, REG_CFG_DONE, 0x01);
815     return 0;
816 }
817
818
819 int rk29_set_cursor_test(struct fb_info *info)
820 {
821         struct rk29fb_inf *inf = dev_get_drvdata(info->device);
822         rk29_set_cursor_colour_map(inf, 0x000000ff, 0x00ff0000);
823         rk29_set_cursor_pos(inf, 0, 0);
824         rk29_set_cursor_img(inf, 0);
825         rk29_set_cursor_en(inf, 1);
826         return 0;
827 }
828 #if 0
829
830 int rk29_set_cursor(struct fb_info *info, struct fb_cursor *cursor)
831 {
832     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
833
834     //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
835
836     /* check not being asked to exceed capabilities */
837
838     if (cursor->image.width > 32)
839         return -EINVAL;
840
841     if (cursor->image.height > 32)
842         return -EINVAL;
843
844     if (cursor->image.depth > 1)
845         return -EINVAL;
846
847     if (cursor->enable)
848         LcdSetBit(inf, SYS_CONFIG, m_HWC_ENABLE);
849     else
850         LcdClrBit(inf, SYS_CONFIG, m_HWC_ENABLE);
851
852     /* set data */
853     if (cursor->set & FB_CUR_SETPOS)
854     {
855         unsigned int x = cursor->image.dx;
856         unsigned int y = cursor->image.dy;
857
858         if (x >= 0x800 || y >= 0x800 )
859             return -EINVAL;
860         LcdWrReg(inf, HWC_DSP_ST, v_BIT11LO(x)|v_BIT11HI(y));
861     }
862
863
864     if (cursor->set & FB_CUR_SETCMAP)
865     {
866         unsigned int bg_col = cursor->image.bg_color;
867         unsigned int fg_col = cursor->image.fg_color;
868
869         fbprintk("%s: update cmap (%08x,%08x)\n",
870             __func__, bg_col, fg_col);
871
872         LcdMskReg(inf, HWC_COLOR_LUT0, m_HWC_R|m_HWC_G|m_HWC_B,
873                   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));
874
875         LcdMskReg(inf, HWC_COLOR_LUT2, m_HWC_R|m_HWC_G|m_HWC_B,
876                          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));
877     }
878
879     if ((cursor->set & FB_CUR_SETSIZE ||
880         cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE))
881         && info->screen_base && info->fix.smem_start && info->fix.smem_len)
882     {
883         /* rk29 cursor is a 2 bpp 32x32 bitmap this routine
884          * clears it to transparent then combines the cursor
885          * shape plane with the colour plane to set the
886          * cursor */
887         int x, y;
888         const unsigned char *pcol = cursor->image.data;
889         const unsigned char *pmsk = cursor->mask;
890         void __iomem   *dst;
891         unsigned long cursor_mem_start;
892         unsigned char  dcol = 0;
893         unsigned char  dmsk = 0;
894         unsigned int   op;
895
896         dst = info->screen_base + info->fix.smem_len - CURSOR_BUF_SIZE;
897             cursor_mem_start = info->fix.smem_start + info->fix.smem_len - CURSOR_BUF_SIZE;
898
899         fbprintk("%s: setting shape (%d,%d)\n",
900             __func__, cursor->image.width, cursor->image.height);
901
902         memset(dst, 0, CURSOR_BUF_SIZE);
903
904         for (y = 0; y < cursor->image.height; y++)
905         {
906             for (x = 0; x < cursor->image.width; x++)
907             {
908                 if ((x % 8) == 0) {
909                     dcol = *pcol++;
910                     dmsk = *pmsk++;
911                 } else {
912                     dcol >>= 1;
913                     dmsk >>= 1;
914                 }
915
916                 if (dmsk & 1) {
917                     op = (dcol & 1) ? 1 : 3;
918                     op <<= ((x % 4) * 2);
919                     *(u8*)(dst+(x/4)) |= op;
920                 }
921             }
922             dst += (32*2)/8;
923         }
924         LcdSetBit(inf, SYS_CONFIG,m_HWC_RELOAD_EN);
925         LcdWrReg(inf, HWC_MST, cursor_mem_start);
926         // flush end when wq_condition=1 in mcu panel, but not in rgb panel
927         if(SCREEN_MCU == inf->cur_screen->type) {
928             wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
929             wq_condition = 0;
930         } else {
931             wq_condition = 0;
932             wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
933         }
934         LcdClrBit(inf, SYS_CONFIG, m_HWC_RELOAD_EN);
935     }
936
937     return 0;
938 }
939 #endif
940 static int hdmi_get_fbscale(void)
941 {
942 #ifdef CONFIG_HDMI
943         return hdmi_get_scale();
944 #else
945         return 100;
946 #endif
947 }
948 static void hdmi_set_fbscale(struct fb_info *info)
949 {
950 #ifdef CONFIG_HDMI
951     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
952     struct rk29fb_screen *screen = inf->cur_screen;
953     struct win0_par *par = info->par;
954         int scale;
955         
956         scale = hdmi_get_scale();
957         if(scale == 100)
958                 return;
959         par->xpos += screen->x_res * (100-scale) / 200;
960         par->ypos += screen->y_res * (100-scale) / 200;
961         par->xsize = par->xsize *scale /100;
962         par->ysize = par->ysize *scale /100;
963 #endif
964 }
965 static int win0_blank(int blank_mode, struct fb_info *info)
966 {
967     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
968
969     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
970
971         CHK_SUSPEND(inf);
972
973     switch(blank_mode)
974     {
975     case FB_BLANK_UNBLANK:
976         LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(1));
977         LcdWrReg(inf, REG_CFG_DONE, 0x01);
978         break;
979     default:
980         LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(0));
981         LcdWrReg(inf, REG_CFG_DONE, 0x01);
982 #ifdef CONFIG_DDR_RECONFIG
983         msleep(40);
984 #endif
985         break;
986     }
987
988         mcu_refresh(inf);
989     return 0;
990 }
991
992 static int win0_set_par(struct fb_info *info)
993 {
994     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
995     struct rk29fb_screen *screen = inf->cur_screen;
996     struct fb_var_screeninfo *var = &info->var;
997     struct fb_fix_screeninfo *fix = &info->fix;
998     struct win0_par *par = info->par;
999         u32 xact, yact, xvir, yvir, xpos, ypos, ScaleYrgbX,ScaleYrgbY, ScaleCbrX, ScaleCbrY, y_addr,uv_addr;
1000         hdmi_set_fbscale(info);
1001         xact = var->xres;                           /* visible resolution               */
1002         yact = var->yres;
1003         xvir = var->xres_virtual;               /* virtual resolution           */
1004         yvir = var->yres_virtual;
1005         //u32 xact_st = var->xoffset;         /* offset from virtual to visible */
1006         //u32 yact_st = var->yoffset;         /* resolution                     */
1007     xpos = par->xpos;
1008     ypos = par->ypos;
1009
1010     ScaleYrgbX=0x1000;
1011         ScaleYrgbY=0x1000;
1012     ScaleCbrX=0x1000;
1013         ScaleCbrY=0x1000;
1014
1015     y_addr = 0;       //user alloc buf addr y
1016     uv_addr = 0;
1017
1018     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1019
1020         CHK_SUSPEND(inf);
1021
1022     if(((var->rotate == 270)||(var->rotate == 90) || (var->rotate == 180)) && (inf->video_mode))
1023     {
1024       #ifdef CONFIG_FB_ROTATE_VIDEO  
1025     //    if(xact > screen->x_res)
1026         {
1027             xact = screen->x_res;       /* visible resolution       */
1028             yact = screen->y_res;
1029             xvir = screen->x_res;       /* virtual resolution       */
1030             yvir = screen->y_res;
1031         }  // else   {            
1032        //     xact = var->yres;               /* visible resolution       */
1033        //     yact = var->xres;
1034        //     xvir = var->yres_virtual;       /* virtual resolution       */
1035        //     yvir = var->xres_virtual;
1036       //  }
1037       #else //CONFIG_FB_ROTATE_VIDEO
1038         printk("LCDC not support rotate!\n");
1039         return -EINVAL;
1040       #endif
1041     }
1042     
1043         // calculate the display phy address
1044     y_addr = fix->smem_start + par->y_offset;
1045     uv_addr = fix->mmio_start + par->c_offset;
1046
1047     ScaleYrgbX = CalScaleW0(xact, par->xsize);
1048     ScaleYrgbY = CalScaleW0(yact, par->ysize);
1049
1050     switch (par->format)
1051     {
1052        case 2:// yuv422
1053            ScaleCbrX= CalScaleW0((xact/2), par->xsize);
1054            ScaleCbrY =  CalScaleW0(yact, par->ysize);
1055            break;
1056        case 3: // yuv4200
1057        case 4: // yuv4201
1058            ScaleCbrX= CalScaleW0(xact/2, par->xsize);
1059            ScaleCbrY =  CalScaleW0(yact/2, par->ysize);
1060            break;
1061        case 5:// yuv444
1062            ScaleCbrX= CalScaleW0(xact, par->xsize);
1063            ScaleCbrY =  CalScaleW0(yact, par->ysize);
1064            break;
1065        default:
1066            break;
1067     }
1068
1069     xpos += (screen->left_margin + screen->hsync_len);
1070     ypos += (screen->upper_margin + screen->vsync_len);
1071
1072     LcdWrReg(inf, WIN0_YRGB_MST, y_addr);
1073     LcdWrReg(inf, WIN0_CBR_MST, uv_addr);
1074
1075     LcdMskReg(inf, SYS_CONFIG,  m_W0_FORMAT , v_W0_FORMAT(par->format));//(inf->video_mode==0)
1076
1077     LcdMskReg(inf, WIN0_VIR, m_WORDLO | m_WORDHI, v_VIRWIDTH(xvir) | v_VIRHEIGHT((yvir)) );
1078     LcdMskReg(inf, WIN0_ACT_INFO, m_WORDLO | m_WORDHI, v_WORDLO(xact) | v_WORDHI(yact));
1079     LcdMskReg(inf, WIN0_DSP_ST, m_BIT11LO | m_BIT11HI, v_BIT11LO(xpos) | v_BIT11HI(ypos));
1080     LcdMskReg(inf, WIN0_DSP_INFO, m_BIT12LO | m_BIT12HI,  v_BIT12LO(par->xsize) | v_BIT12HI(par->ysize));
1081     LcdMskReg(inf, WIN0_SCL_FACTOR_YRGB, m_WORDLO | m_WORDHI, v_WORDLO(ScaleYrgbX) | v_WORDHI(ScaleYrgbY));
1082     LcdMskReg(inf, WIN0_SCL_FACTOR_CBR, m_WORDLO | m_WORDHI, v_WORDLO(ScaleCbrX) | v_WORDHI(ScaleCbrY));
1083
1084     switch(par->format)
1085     {
1086     case 0:  //rgb888
1087         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,
1088             v_W0_YRGB_8_SWAP(1) | v_W0_YRGB_16_SWAP(1) | v_W0_YRGB_R_SHIFT_SWAP(1) | v_W0_565_RB_SWAP(0) | v_W0_YRGB_M8_SWAP(0) | v_W0_CBR_8_SWAP(0));
1089                 break;
1090     case 1:  //rgb565
1091         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,
1092             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));
1093         break;
1094     case 4:   //yuv4201
1095         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,
1096             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) |
1097             v_W0_YRGB_M8_SWAP(1) | v_W0_CBR_8_SWAP(0));
1098         break;
1099     default:
1100         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,
1101             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) );
1102                 break;
1103     }
1104
1105     LcdWrReg(inf, REG_CFG_DONE, 0x01);
1106
1107     return 0;
1108
1109 }
1110
1111 static int win0_pan( struct fb_info *info )
1112 {
1113     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1114    // struct fb_var_screeninfo *var0 = &info->var;
1115     struct fb_fix_screeninfo *fix0 = &info->fix;
1116     struct win0_par *par = info->par;
1117     u32 y_addr=0, uv_addr=0;
1118
1119     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1120
1121         CHK_SUSPEND(inf);
1122
1123     y_addr = fix0->smem_start +  par->y_offset;//y_offset;
1124     uv_addr = fix0->mmio_start + par->c_offset ;//c_offset;
1125
1126     LcdWrReg(inf, WIN0_YRGB_MST, y_addr);
1127     LcdWrReg(inf, WIN0_CBR_MST, uv_addr);
1128     LcdWrReg(inf, REG_CFG_DONE, 0x01);
1129
1130      // enable win0 after the win0 addr is seted
1131         LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE((1==par->addr_seted)?(1):(0)));
1132         mcu_refresh(inf);
1133
1134     return 0;
1135 }
1136
1137 static int win1_blank(int blank_mode, struct fb_info *info)
1138 {
1139     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1140
1141     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1142
1143         CHK_SUSPEND(inf);
1144
1145         switch(blank_mode)
1146     {
1147     case FB_BLANK_UNBLANK:
1148         LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(1));
1149         break;
1150     default:
1151         LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0));
1152         break;
1153     }
1154     LcdWrReg(inf, REG_CFG_DONE, 0x01);
1155
1156         mcu_refresh(inf);
1157     return 0;
1158 }
1159
1160 static int win1_set_par(struct fb_info *info)
1161 {
1162     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1163     struct fb_fix_screeninfo *fix = &info->fix;
1164     struct rk29fb_screen *screen = inf->cur_screen;
1165     struct win0_par *par = info->par;
1166     struct fb_var_screeninfo *var = &info->var;
1167         u32 addr;
1168         u16 xres_virtual,xpos,ypos;
1169         u8 trspval,trspmode;
1170     if(((screen->x_res != var->xres) || (screen->y_res != var->yres))
1171         && !((screen->x_res>1280) && (var->bits_per_pixel == 32)))
1172     {
1173         hdmi_set_fbscale(info);
1174     }else  if(((screen->x_res==1920) ))
1175         {
1176         if(hdmi_get_fbscale() < 100)
1177                         par->ypos -=screen->y_res * (100-hdmi_get_fbscale()) / 200;
1178         }
1179     //u32 offset=0, addr=0, map_size=0, smem_len=0;
1180     addr=0;
1181     xres_virtual = 0;      //virtual screen size
1182
1183     //u16 xpos_virtual = var->xoffset;           //visiable offset in virtual screen
1184     //u16 ypos_virtual = var->yoffset;
1185
1186     xpos = par->xpos;                 //visiable offset in panel
1187     ypos = par->ypos;
1188
1189     trspmode = TRSP_CLOSE;
1190     trspval = 0;
1191
1192     //fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1193
1194    #ifdef CONFIG_FB_SCALING_OSD
1195     if(((screen->x_res != var->xres) || (screen->y_res != var->yres))
1196         && !((screen->x_res>1280) && (var->bits_per_pixel == 32)))
1197     {
1198         addr = fix->mmio_start + par->y_offset* hdmi_get_fbscale()/100;
1199         xres_virtual = screen->x_res* hdmi_get_fbscale()/100;      //virtual screen size
1200     }
1201     else
1202    #endif
1203     {
1204         addr = fix->smem_start + par->y_offset;
1205         xres_virtual = var->xres_virtual;      //virtual screen size
1206     }
1207     LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE|m_W1_FORMAT, v_W1_ENABLE(1)|v_W1_FORMAT(par->format));
1208
1209     xpos += (screen->left_margin + screen->hsync_len);
1210     ypos += (screen->upper_margin + screen->vsync_len);
1211
1212     LcdWrReg(inf, WIN1_YRGB_MST, addr);
1213
1214     LcdMskReg(inf, WIN1_DSP_ST, m_BIT11LO|m_BIT11HI, v_BIT11LO(xpos) | v_BIT11HI(ypos));
1215     LcdMskReg(inf, WIN1_DSP_INFO, m_BIT12LO|m_BIT12HI, v_BIT12LO(par->xsize) | v_BIT12HI(par->ysize));
1216
1217     LcdMskReg(inf, WIN1_VIR, m_WORDLO , v_WORDLO(xres_virtual));
1218
1219     LcdMskReg(inf, BLEND_CTRL, m_W1_BLEND_EN |  m_W1_BLEND_FACTOR,
1220         v_W1_BLEND_EN((TRSP_FMREG==trspmode) || (TRSP_MASK==trspmode)) | v_W1_BLEND_FACTOR(trspval));
1221
1222      // enable win1 color key and set the color to black(rgb=0)
1223     LcdMskReg(inf, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR, v_COLORKEY_EN(1) | v_KEYCOLOR(0));
1224
1225     if(1==par->format) //rgb565
1226     {
1227         LcdMskReg(inf, SWAP_CTRL, m_W1_8_SWAP | m_W1_16_SWAP | m_W1_R_SHIFT_SWAP | m_W1_565_RB_SWAP,
1228             v_W1_8_SWAP(0) | v_W1_16_SWAP(0) | v_W1_R_SHIFT_SWAP(0) | v_W1_565_RB_SWAP(0) );
1229     }
1230     else
1231     {
1232          LcdMskReg(inf, SWAP_CTRL, m_W1_8_SWAP | m_W1_16_SWAP | m_W1_R_SHIFT_SWAP | m_W1_565_RB_SWAP,
1233                 v_W1_8_SWAP(1) | v_W1_16_SWAP(1) | v_W1_R_SHIFT_SWAP(1) | v_W1_565_RB_SWAP(0) );
1234
1235          LcdMskReg(inf, DSP_CTRL0, m_W1_TRANSP_FROM, v_W1_TRANSP_FROM(TRSP_FMRAM==trspmode) );
1236     }
1237
1238         LcdWrReg(inf, REG_CFG_DONE, 0x01);
1239
1240     return 0;
1241 }
1242
1243 static int win1_pan( struct fb_info *info )
1244 {
1245     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1246     struct fb_fix_screeninfo *fix1 = &info->fix;
1247     struct win0_par *par = info->par;
1248     u32 addr = 0;
1249
1250     #ifdef CONFIG_FB_SCALING_OSD
1251     struct rk29fb_screen *screen = inf->cur_screen;
1252     struct fb_var_screeninfo *var = &info->var;
1253     if(((screen->x_res != var->xres) || (screen->y_res != var->yres))
1254         && !((screen->x_res>1280) && (var->bits_per_pixel == 32)))
1255     {
1256         addr = fix1->mmio_start + par->y_offset* hdmi_get_fbscale()/100;
1257     }
1258     else
1259     #endif
1260     {
1261         addr = fix1->smem_start + par->y_offset;
1262     }
1263
1264     //fbprintk("info->screen_base = %8x ; fix1->smem_len = %d , addr = %8x\n",(u32)info->screen_base, fix1->smem_len, addr);
1265
1266     LcdWrReg(inf, WIN1_YRGB_MST, addr);
1267     LcdWrReg(inf, REG_CFG_DONE, 0x01);
1268         mcu_refresh(inf);
1269
1270     return 0;
1271 }
1272
1273 static int fb0_blank(int blank_mode, struct fb_info *info)
1274 {
1275         struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1276
1277     if(inf->video_mode == 1)
1278     {
1279         win1_blank(blank_mode, info);
1280     }
1281     else
1282     {
1283         win0_blank(blank_mode, info);
1284     }
1285     return 0;
1286 }
1287
1288 static int fb0_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1289 {
1290     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1291     struct rk29fb_screen *screen = inf->cur_screen;
1292     u16 xpos = (var->nonstd>>8) & 0xfff;
1293     u16 ypos = (var->nonstd>>20) & 0xfff;
1294     u16 xlcd = screen->x_res;
1295     u16 ylcd = screen->y_res;
1296
1297     //fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1298
1299         CHK_SUSPEND(inf);
1300
1301     if( 0==var->xres_virtual || 0==var->yres_virtual ||
1302         0==var->xres || 0==var->yres || var->xres<16 ||
1303         ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) )
1304     {
1305         printk(">>>>>> fb0_check_var fail 1!!! \n");
1306         printk(">>>>>> 0==%d || 0==%d ", var->xres_virtual,var->yres_virtual);
1307         printk("0==%d || 0==%d || %d<16 || ", var->xres,var->yres,var->xres<16);
1308         printk("bits_per_pixel=%d \n", var->bits_per_pixel);
1309         return -EINVAL;
1310     }
1311
1312     if( (var->xoffset+var->xres)>var->xres_virtual ||
1313         (var->yoffset+var->yres)>var->yres_virtual )
1314     {
1315         printk(">>>>>> fb0_check_var fail 2!!! \n");
1316         printk(">>>>>> (%d+%d)>%d || ", var->xoffset,var->xres,var->xres_virtual);
1317         printk("(%d+%d)>%d || ", var->yoffset,var->yres,var->yres_virtual);
1318         printk("(%d+%d)>%d || (%d+%d)>%d \n", xpos,var->xres,xlcd,ypos,var->yres,ylcd);
1319         return -EINVAL;
1320     }
1321
1322     if(inf->fb0_color_deepth)var->bits_per_pixel=inf->fb0_color_deepth;
1323     switch(var->bits_per_pixel)
1324     {
1325     case 16:    // rgb565
1326         var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1);
1327         var->xres = (var->xres + 0x1) & (~0x1);
1328         var->xoffset = (var->xoffset) & (~0x1);
1329         break;
1330     default:    // rgb888
1331         var->bits_per_pixel = 32;
1332         break;
1333     }
1334
1335     return 0;
1336 }
1337
1338
1339 static int fb0_set_par(struct fb_info *info)
1340 {
1341     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1342     struct fb_var_screeninfo *var = &info->var;
1343     struct fb_fix_screeninfo *fix = &info->fix;
1344     struct rk29fb_screen *screen = inf->cur_screen;
1345     struct win0_par *par = info->par;
1346
1347     u32 offset=0,  smem_len=0;
1348     u16 xres_virtual = var->xres_virtual;      //virtual screen size
1349     u16 xpos_virtual = var->xoffset;           //visiable offset in virtual screen
1350     u16 ypos_virtual = var->yoffset;
1351
1352 #ifdef CONFIG_FB_SCALING_OSD
1353     struct rk29_ipp_req ipp_req;
1354     u32 dstoffset=0;
1355 #endif
1356
1357     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1358
1359     inf->setFlag = 0;
1360         CHK_SUSPEND(inf);
1361
1362     if(inf->fb0_color_deepth)var->bits_per_pixel=inf->fb0_color_deepth;
1363     #if !defined(CONFIG_FB_SCALING_OSD)
1364     if((inf->video_mode == 1)&&(screen->y_res < var->yres))ypos_virtual += (var->yres-screen->y_res);
1365     #endif
1366
1367     switch(var->bits_per_pixel)
1368     {
1369     case 16:    // rgb565
1370         par->format = 1;
1371         //fix->line_length = 2 * xres_virtual;
1372         fix->line_length = (inf->fb0_color_deepth ? 4:2) * xres_virtual;   //32bit and 16bit change
1373
1374         #ifdef CONFIG_FB_SCALING_OSD
1375         dstoffset = ((ypos_virtual*screen->y_res/var->yres) *screen->x_res + (xpos_virtual*screen->x_res)/var->xres )*2;
1376         ipp_req.src0.fmt = IPP_RGB_565;
1377         ipp_req.dst0.fmt = IPP_RGB_565;
1378         #endif
1379         offset = (ypos_virtual*xres_virtual + xpos_virtual)*(inf->fb0_color_deepth ? 4:2);
1380         break;
1381     case 32:    // rgb888
1382     default:
1383         par->format = 0;
1384         fix->line_length = 4 * xres_virtual;
1385         #ifdef CONFIG_FB_SCALING_OSD
1386         dstoffset = ((ypos_virtual*screen->y_res/var->yres) *screen->x_res + (xpos_virtual*screen->x_res)/var->xres )*4;
1387         ipp_req.src0.fmt = IPP_XRGB_8888;
1388         ipp_req.dst0.fmt = IPP_XRGB_8888;
1389         #endif
1390         offset = (ypos_virtual*xres_virtual + xpos_virtual)*4;
1391         break;
1392     }
1393
1394     smem_len = fix->line_length * var->yres_virtual;
1395     //map_size = PAGE_ALIGN(smem_len);
1396
1397     if (smem_len > fix->smem_len)     // buffer need realloc
1398     {
1399         printk("%s sorry!!! win1 buf is not enough\n",__FUNCTION__);
1400         printk("line_length = %d, yres_virtual = %d, win1_buf only = %dB\n",fix->line_length,var->yres_virtual,fix->smem_len);
1401         printk("you can change buf size MEM_FB_SIZE in board-xxx.c \n");
1402     }
1403
1404
1405     par->addr_seted = 1;
1406 #if ANDROID_USE_THREE_BUFS
1407     if(0==new_frame_seted) {
1408         wq_condition = 0;
1409         wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
1410     }
1411     new_frame_seted = 0;
1412 #endif
1413
1414     if(inf->video_mode == 1)
1415     {
1416         #ifdef CONFIG_FB_SCALING_OSD
1417         if(((screen->x_res != var->xres) || (screen->y_res != var->yres))
1418         && !((screen->x_res>1280) && (var->bits_per_pixel == 32)))
1419         {
1420             par->xpos = 0;
1421             par->ypos = 0;
1422             par->xsize = screen->x_res;
1423             par->ysize = screen->y_res;
1424             par->y_offset = dstoffset;
1425
1426             ipp_req.src0.YrgbMst = fix->smem_start + offset;
1427             ipp_req.src0.w = var->xres;
1428             ipp_req.src0.h = var->yres;
1429
1430             ipp_req.dst0.YrgbMst = fix->mmio_start + dstoffset* hdmi_get_fbscale()/100;
1431             ipp_req.dst0.w = screen->x_res* hdmi_get_fbscale()/100;
1432             ipp_req.dst0.h = screen->y_res* hdmi_get_fbscale()/100;
1433
1434             ipp_req.src_vir_w = ipp_req.src0.w;
1435             ipp_req.dst_vir_w = ipp_req.dst0.w;
1436             ipp_req.timeout = 100;
1437             ipp_req.flag = IPP_ROT_0;
1438             //ipp_do_blit(&ipp_req);
1439             ipp_blit_sync(&ipp_req);
1440         }else
1441         #endif
1442         {
1443             par->y_offset = offset;
1444             par->xpos = (screen->x_res >= var->xres)?((screen->x_res - var->xres)/2):0;              //visiable offset in panel
1445             par->ypos = (screen->y_res >= var->yres)?(screen->y_res - var->yres):0;
1446             par->xsize = var->xres;                                //visiable size in panel
1447             par->ysize = (screen->y_res >= var->yres) ? var->yres : screen->y_res;
1448         }
1449         win1_set_par(info);
1450     }
1451     else
1452     {
1453         par->y_offset = offset;
1454         par->xpos = 0;
1455         par->ypos = 0;
1456         par->xsize = screen->x_res;
1457         par->ysize = screen->y_res;
1458         win0_set_par(info);
1459     }
1460     inf->setFlag = 1;
1461     return 0;
1462 }
1463
1464 static int fb0_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1465 {
1466
1467     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1468     struct fb_var_screeninfo *var1 = &info->var;
1469     struct rk29fb_screen *screen = inf->cur_screen;
1470     struct win0_par *par = info->par;
1471
1472     u32 offset = 0;
1473     u16 ypos_virtual = var->yoffset;
1474     u16 xpos_virtual = var->xoffset;
1475    #ifdef CONFIG_FB_SCALING_OSD
1476     struct fb_fix_screeninfo *fix = &info->fix;
1477     struct rk29_ipp_req ipp_req;
1478     u32 dstoffset = 0;
1479    #endif
1480         //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1481
1482         CHK_SUSPEND(inf);
1483
1484     if(inf->fb0_color_deepth)var->bits_per_pixel=inf->fb0_color_deepth;
1485     #if !defined(CONFIG_FB_SCALING_OSD)
1486         if((inf->video_mode == 1)&&(screen->y_res < var->yres))ypos_virtual += (var->yres-screen->y_res);
1487     #endif
1488
1489     switch(var1->bits_per_pixel)
1490     {
1491     case 16:    // rgb565
1492         var->xoffset = (var->xoffset) & (~0x1);
1493         #ifdef CONFIG_FB_SCALING_OSD
1494         dstoffset = ((ypos_virtual*screen->y_res/var->yres) *screen->x_res + (xpos_virtual*screen->x_res)/var->xres) * 2;
1495         ipp_req.src0.fmt = IPP_RGB_565;
1496         ipp_req.dst0.fmt = IPP_RGB_565;
1497         #endif
1498         offset = (ypos_virtual*var1->xres_virtual + xpos_virtual)*(inf->fb0_color_deepth ? 4:2);
1499         break;
1500     case 32:    // rgb888
1501         #ifdef CONFIG_FB_SCALING_OSD
1502         dstoffset = ((ypos_virtual*screen->y_res/var->yres) *screen->x_res + (xpos_virtual*screen->x_res)/var->xres )*4;
1503         ipp_req.src0.fmt = IPP_XRGB_8888;
1504         ipp_req.dst0.fmt = IPP_XRGB_8888;
1505         #endif
1506         offset = (ypos_virtual*var1->xres_virtual + xpos_virtual)*4;
1507         break;
1508     default:
1509         return -EINVAL;
1510     }
1511
1512     if(inf->video_mode == 1)
1513     {
1514         #ifdef CONFIG_FB_SCALING_OSD
1515         if(((screen->x_res != var->xres) || (screen->y_res != var->yres))
1516         && !((screen->x_res>1280) && (var->bits_per_pixel == 32)))
1517         {
1518             par->y_offset = dstoffset;
1519
1520             ipp_req.src0.YrgbMst = fix->smem_start + offset;
1521             ipp_req.src0.w = var->xres;
1522             ipp_req.src0.h = var->yres;
1523
1524             ipp_req.dst0.YrgbMst = fix->mmio_start + dstoffset* hdmi_get_fbscale()/100;
1525             ipp_req.dst0.w = screen->x_res* hdmi_get_fbscale()/100;
1526             ipp_req.dst0.h = screen->y_res* hdmi_get_fbscale()/100;
1527
1528             ipp_req.src_vir_w = ipp_req.src0.w;
1529             ipp_req.dst_vir_w = ipp_req.dst0.w;
1530             ipp_req.timeout = 100;
1531             ipp_req.flag = IPP_ROT_0;
1532             //ipp_do_blit(&ipp_req);
1533             ipp_blit_sync(&ipp_req);
1534             win1_pan(info);
1535             return 0;
1536         }else
1537         #endif
1538             par->y_offset = offset;
1539         win1_pan(info);
1540     }
1541     else
1542     {
1543         par->y_offset = offset;
1544         win0_pan(info);
1545     }
1546         // flush end when wq_condition=1 in mcu panel, but not in rgb panel
1547 #if !ANDROID_USE_THREE_BUFS
1548     // flush end when wq_condition=1 in mcu panel, but not in rgb panel
1549     if(SCREEN_MCU == inf->cur_screen->type) {
1550         wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
1551         wq_condition = 0;
1552     } else {
1553         wq_condition = 0;
1554         wait_event_interruptible_timeout(wq, wq_condition, HZ/20);
1555     }
1556 #endif
1557     return 0;
1558 }
1559
1560 static int fb0_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
1561 {
1562     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1563         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
1564
1565         CHK_SUSPEND(inf);
1566
1567     switch(cmd)
1568     {
1569     case FB0_IOCTL_STOP_TIMER_FLUSH:    //stop timer flush mcu panel after android is runing
1570         if(1==arg)
1571         {
1572             inf->mcu_usetimer = 0;
1573         }
1574         break;
1575    case FBIOPUT_16OR32:
1576
1577         inf->fb0_color_deepth = arg;
1578
1579             break;
1580         case FBIOPUT_FBPHYADD:
1581         return info->fix.smem_start;
1582     case FBIOGET_OVERLAY_STATE:
1583         return inf->video_mode;
1584     case FBIOGET_SCREEN_STATE:
1585         return inf->cur_screen->type;
1586         
1587         case FBIOPUT_SET_CURSOR_EN:
1588                 {
1589                         int en;
1590                         if(copy_from_user(&en, (void*)arg, sizeof(int)))
1591                             return -EFAULT;
1592                         rk29_set_cursor_en(inf, en);
1593                 }
1594                 break;
1595         case FBIOPUT_SET_CURSOR_POS:
1596                 {
1597                         struct fbcurpos pos;
1598                         if(copy_from_user(&pos, (void*)arg, sizeof(struct fbcurpos)))
1599                             return -EFAULT;
1600                         rk29_set_cursor_pos(inf, pos.x , pos.y);
1601                 }
1602                 break;
1603         case FBIOPUT_SET_CURSOR_IMG:
1604                 {
1605                         char cursor_buf[CURSOR_BUF_SIZE];
1606                         if(copy_from_user(cursor_buf, (void*)arg, CURSOR_BUF_SIZE))
1607                                 return -EFAULT;
1608                         rk29_set_cursor_img(inf, cursor_buf);
1609                 }
1610                 break;
1611         case FBIOPUT_SET_CURSOR_CMAP:
1612                 {
1613                         struct fb_image img;
1614                         if(copy_from_user(&img, (void*)arg, sizeof(struct fb_image)))
1615                             return -EFAULT;
1616                         rk29_set_cursor_colour_map(inf, img.bg_color, img.fg_color);
1617                 }
1618                 break;
1619         case FBIOPUT_GET_CURSOR_RESOLUTION:
1620                 {
1621             u32 panel_size[2];
1622                         //struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1623              if(inf->fb1->var.rotate == 270) {
1624                 panel_size[0] = inf->cur_screen->y_res; //inf->cur_screen->y_res; change for hdmi video size
1625                 panel_size[1] = inf->cur_screen->x_res;
1626             } else {
1627                 panel_size[0] = inf->cur_screen->x_res;
1628                 panel_size[1] = inf->cur_screen->y_res;
1629             }
1630             if(copy_to_user((void*)arg, panel_size, 8))  return -EFAULT;
1631             break;
1632                 }
1633         case FBIOPUT_GET_CURSOR_EN:
1634                 {
1635             u32 en = (inf->regbak.SYS_CONFIG & m_HWC_ENABLE);
1636             if(copy_to_user((void*)arg, &en, 4))  return -EFAULT;
1637             break;
1638                 }
1639    default:
1640         break;
1641     }
1642     return 0;
1643 }
1644
1645 static int fb1_blank(int blank_mode, struct fb_info *info)
1646 {
1647     win0_blank(blank_mode, info);
1648     return 0;
1649 }
1650
1651 static int fb1_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1652 {
1653     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1654     struct rk29fb_screen *screen = inf->cur_screen;
1655
1656     u32 ScaleYRGBY=0x1000;
1657     u16 xpos = (var->nonstd>>8) & 0xfff;   //offset in panel
1658     u16 ypos = (var->nonstd>>20) & 0xfff;
1659     u16 xsize = (var->grayscale>>8) & 0xfff;   //visiable size in panel
1660     u16 ysize = (var->grayscale>>20) & 0xfff;
1661     u16 xlcd = screen->x_res;        //size of panel
1662     u16 ylcd = screen->y_res;
1663     u16 yres = 0;
1664 #if 0
1665         struct hdmi *hdmi = get_hdmi_struct(0);
1666 #endif
1667
1668     if((var->rotate == 270)||(var->rotate == 90)) {
1669       #ifdef CONFIG_FB_ROTATE_VIDEO
1670         xlcd = screen->y_res;
1671         ylcd = screen->x_res;
1672       #else //CONFIG_FB_ROTATE_VIDEO
1673         printk("LCDC not support rotate!\n");
1674         return -EINVAL;
1675       #endif
1676     }
1677
1678     xpos = (xpos * screen->x_res) / inf->panel1_info.x_res;
1679     ypos = (ypos * screen->y_res) / inf->panel1_info.y_res;
1680     xsize = (xsize * screen->x_res) / inf->panel1_info.x_res;
1681     ysize = (ysize * screen->y_res) / inf->panel1_info.y_res;
1682
1683     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1684
1685         CHK_SUSPEND(inf);
1686
1687     if( 0==var->xres_virtual || 0==var->yres_virtual ||
1688         0==var->xres || 0==var->yres || var->xres<16 ||
1689         0==xsize || 0==ysize || xsize<16 ||
1690         ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) )
1691     {
1692         printk(">>>>>> win0fb_check_var fail 1!!! \n");
1693                 printk("0==%d || 0==%d || 0==%d || 0==%d || %d<16 \n ||0==%d || 0==%d || %d<16 ||((16!=%d)&&(32!=%d)) \n",
1694                                 var->xres_virtual, var->yres_virtual, var->xres, var->yres, var->xres, xsize, ysize, xsize,
1695                         var->bits_per_pixel, var->bits_per_pixel);
1696         return -EINVAL;
1697     }
1698
1699     if( (var->xoffset+var->xres)>var->xres_virtual ||
1700         (var->yoffset+var->yres)>var->yres_virtual ||
1701         (xpos+xsize)>xlcd || (ypos+ysize)>ylcd  )
1702     {
1703         printk(">>>>>> win0fb_check_var fail 2!!! \n");
1704                 printk("(%d+%d)>%d || (%d+%d)>%d || (%d+%d)>%d || (%d+%d)>%d \n ",
1705                                 var->xoffset, var->xres, var->xres_virtual, var->yoffset, var->yres,
1706                                 var->yres_virtual, xpos, xsize, xlcd, ypos, ysize, ylcd);       
1707         return -EINVAL;
1708     }
1709
1710     switch(var->nonstd&0x0f)
1711     {
1712     case 0: // rgb
1713         switch(var->bits_per_pixel)
1714         {
1715         case 16:    // rgb565
1716             var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1);
1717             var->xres = (var->xres + 0x1) & (~0x1);
1718             var->xoffset = (var->xoffset) & (~0x1);
1719             break;
1720         default:    // rgb888
1721             var->bits_per_pixel = 32;
1722             break;
1723         }
1724         var->nonstd &= ~0xc0;  //not support I2P in this format
1725         break;
1726     case 1: // yuv422
1727         var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
1728         var->xres = (var->xres + 0x3) & (~0x3);
1729         var->xoffset = (var->xoffset) & (~0x3);
1730         break;
1731     case 2: // yuv4200
1732         var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
1733         var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1);
1734         var->xres = (var->xres + 0x3) & (~0x3);
1735         var->yres = (var->yres + 0x1) & (~0x1);
1736         var->xoffset = (var->xoffset) & (~0x3);
1737         var->yoffset = (var->yoffset) & (~0x1);
1738         break;
1739     case 3: // yuv4201
1740         var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
1741         var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1);
1742         var->xres = (var->xres + 0x3) & (~0x3);
1743         var->yres = (var->yres + 0x1) & (~0x1);
1744         var->xoffset = (var->xoffset) & (~0x3);
1745         var->yoffset = (var->yoffset) & (~0x1);
1746         var->nonstd &= ~0xc0;   //not support I2P in this format
1747         break;
1748     case 4: // none
1749     case 5: // yuv444
1750         var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
1751         var->xres = (var->xres + 0x3) & (~0x3);
1752         var->xoffset = (var->xoffset) & (~0x3);
1753         var->nonstd &= ~0xc0;   //not support I2P in this format
1754         break;
1755     default:
1756         printk(">>>>>> fb1 var->nonstd=%d is invalid! \n", var->nonstd);
1757         return -EINVAL;
1758     }
1759
1760     if((var->rotate == 270)||(var->rotate == 90))
1761      {
1762          yres = var->xres;
1763      }
1764      else
1765      {
1766          yres = var->yres;
1767      }
1768
1769     ScaleYRGBY = CalScaleW0(yres, ysize);
1770
1771     if((ScaleYRGBY>0x8000) || (ScaleYRGBY<0x200))
1772     {
1773         return -EINVAL;        // multiple of scale down or scale up can't exceed 8
1774     }
1775 #if 0
1776         if(inf->video_mode == 1) {
1777                 if(hdmi_resolution_changed(hdmi,var->xres,var->yres, 1) == 1)
1778                 {
1779                         LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE,  v_BLACK_MODE(1));
1780                 LcdWrReg(inf, REG_CFG_DONE, 0x01);
1781                         init_completion(&hdmi->complete);
1782                         hdmi->wait = 1;
1783                         wait_for_completion_interruptible_timeout(&hdmi->complete,
1784                                                                 msecs_to_jiffies(10000));
1785                 }
1786         }
1787 #endif
1788     return 0;
1789 }
1790
1791 static int fb1_set_par(struct fb_info *info)
1792 {
1793     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
1794     struct rk29fb_screen *screen = inf->cur_screen;
1795     struct fb_var_screeninfo *var = &info->var;
1796     struct fb_fix_screeninfo *fix = &info->fix;
1797     struct win0_par *par = info->par;
1798
1799     u8 format = 0;
1800     u32 cblen=0, crlen=0, map_size=0, smem_len=0;
1801
1802         //u32 xact = var->xres;                     /* visible resolution               */
1803         //u32 yact = var->yres;
1804         u32 xvir = var->xres_virtual;           /* virtual resolution           */
1805         u32 yvir = var->yres_virtual;
1806         u32 xact_st = var->xoffset;                     /* offset from virtual to visible */
1807         u32 yact_st = var->yoffset;                     /* resolution                   */
1808
1809     u16 xpos = (var->nonstd>>8) & 0xfff;      //visiable pos in panel
1810     u16 ypos = (var->nonstd>>20) & 0xfff;
1811     u16 xsize = (var->grayscale>>8) & 0xfff;  //visiable size in panel
1812     u16 ysize = (var->grayscale>>20) & 0xfff;
1813
1814     //u32 ScaleYrgbX=0x1000,ScaleYrgbY=0x1000;
1815     //u32 ScaleCbrX=0x1000, ScaleCbrY=0x1000;
1816
1817     u8 data_format = var->nonstd&0x0f;
1818    // u32 win0_en = var->reserved[2];
1819    // u32 y_addr = var->reserved[3];       //user alloc buf addr y
1820    // u32 uv_addr = var->reserved[4];
1821
1822     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
1823
1824         CHK_SUSPEND(inf);
1825     if((var->rotate == 270)||(var->rotate == 90))
1826     {
1827         #ifdef CONFIG_FB_ROTATE_VIDEO
1828         xpos = (var->nonstd>>20) & 0xfff;      //visiable pos in panel
1829         ypos = (var->nonstd>>8) & 0xfff;
1830         xsize = (var->grayscale>>20) & 0xfff;  //visiable size in panel
1831         ysize = (var->grayscale>>8) & 0xfff;
1832         #else //CONFIG_FB_ROTATE_VIDEO
1833         printk("LCDC not support rotate!\n");
1834         return -EINVAL;
1835       #endif
1836     } else{
1837         xpos = (xpos * screen->x_res) / inf->panel1_info.x_res;
1838         ypos = (ypos * screen->y_res) / inf->panel1_info.y_res;
1839         xsize = (xsize * screen->x_res) / inf->panel1_info.x_res;
1840         ysize = (ysize * screen->y_res) / inf->panel1_info.y_res;
1841     }
1842         /* calculate y_offset,c_offset,line_length,cblen and crlen  */
1843     switch (data_format)
1844     {
1845     case 0: // rgb
1846         switch(var->bits_per_pixel)
1847         {
1848         case 16:    // rgb565
1849             format = 1;
1850             fix->line_length = 2 * xvir;
1851             par->y_offset = (yact_st*xvir + xact_st)*2;
1852             break;
1853         case 32:    // rgb888
1854             format = 0;
1855             fix->line_length = 4 * xvir;
1856             par->y_offset = (yact_st*xvir + xact_st)*4;
1857             break;
1858         default:
1859             return -EINVAL;
1860         }
1861         break;
1862     case 1: // yuv422
1863         format = 2;
1864         fix->line_length = xvir;
1865         cblen = crlen = (xvir*yvir)/2;
1866         par->y_offset = yact_st*xvir + xact_st;
1867         par->c_offset = yact_st*xvir + xact_st;
1868         break;
1869     case 2: // yuv4200
1870         format = 3;
1871         fix->line_length = xvir;
1872         cblen = crlen = (xvir*yvir)/4;
1873
1874         par->y_offset = yact_st*xvir + xact_st;
1875         par->c_offset = (yact_st/2)*xvir + xact_st;
1876
1877         break;
1878     case 3: // yuv4201
1879         format = 4;
1880         fix->line_length = xvir;
1881         par->y_offset = (yact_st/2)*2*xvir + (xact_st)*2;
1882         par->c_offset = (yact_st/2)*xvir + xact_st;
1883         cblen = crlen = (xvir*yvir)/4;
1884         break;
1885     case 4: // none
1886     case 5: // yuv444
1887         format = 5;
1888         fix->line_length = xvir;
1889         par->y_offset = yact_st*xvir + xact_st;
1890         par->c_offset = yact_st*2*xvir + xact_st*2;
1891         cblen = crlen = (xvir*yvir);
1892         break;
1893     default:
1894         return -EINVAL;
1895     }
1896
1897     smem_len = fix->line_length * yvir + cblen + crlen;
1898     map_size = PAGE_ALIGN(smem_len);
1899
1900    // fix->smem_start = y_addr;
1901     fix->smem_len = smem_len;
1902   //  fix->mmio_start = uv_addr;
1903
1904  //   par->addr_seted = ((-1==(int)y_addr) || (0==(int)y_addr) || (win0_en==0)) ? 0 : 1;
1905     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);
1906
1907     par->format = format;
1908     par->xpos = xpos;
1909     par->ypos = ypos;
1910     par->xsize = xsize;
1911     par->ysize = ysize;
1912     win0_set_par(info);
1913
1914     if ( wq_condition2 == 0 ) {
1915         wait_event_interruptible_timeout(wq,  wq_condition2, HZ/20);
1916     }
1917     wq_condition2 = 0;
1918
1919 #ifdef CONFIG_FB_ROTATE_VIDEO
1920 //need refresh  ,zyc add                
1921         if((has_set_rotate == true) && (last_yuv_phy[0] != 0) && (last_yuv_phy[1] != 0))
1922         {
1923                 u32 yuv_phy[2];
1924                 struct rk29_ipp_req ipp_req;
1925                 static u32 dstoffset = 0;
1926                 static int fb_index = 0;
1927                 
1928                 yuv_phy[0] = last_yuv_phy[0];
1929                 yuv_phy[1] = last_yuv_phy[1];
1930                 yuv_phy[0] += par->y_offset;
1931                 yuv_phy[1] += par->c_offset;
1932         #if 0
1933                 if((var->rotate == 90) ||(var->rotate == 270))
1934         #else
1935         if(var->rotate%360 != 0)
1936         #endif
1937                         {
1938                                 dstoffset = (dstoffset+1)%2;
1939                                 ipp_req.src0.fmt = 3;
1940                                 ipp_req.src0.YrgbMst = yuv_phy[0];
1941                                 ipp_req.src0.CbrMst = yuv_phy[1];
1942                                 ipp_req.src0.w = var->xres;
1943                                 ipp_req.src0.h = var->yres;
1944                                 
1945                                 ipp_req.src_vir_w= (var->xres + 15) & (~15);
1946                                 ipp_req.dst_vir_w=screen->x_res;
1947
1948                                 ipp_req.dst0.fmt = 3;
1949                                 ipp_req.dst0.YrgbMst = inf->fb0->fix.mmio_start + screen->x_res*screen->y_res*2*dstoffset;
1950                                 ipp_req.dst0.CbrMst = inf->fb0->fix.mmio_start + screen->x_res*screen->y_res*(2*dstoffset+1);
1951                                 //   if(var->xres > screen->x_res)
1952                                 //   {
1953                                         ipp_req.dst0.w = var->xres;
1954                                         ipp_req.dst0.h = var->yres;
1955                                 //  }   else    {
1956                                 //        ipp_req.dst0.w = var->yres;
1957                                 //        ipp_req.dst0.h = var->xres;
1958                                 //   }
1959                                 //ipp_req.src_vir_w = ipp_req.src0.w;
1960                                 //ipp_req.dst_vir_w = ipp_req.dst0.w;
1961                                 ipp_req.timeout = 100;
1962                                 if(var->rotate == 90)
1963                                         ipp_req.flag = IPP_ROT_90;
1964                 else if (var->rotate == 180)
1965                                         ipp_req.flag = IPP_ROT_180;
1966                                 else if(var->rotate == 270)
1967                                         ipp_req.flag = IPP_ROT_270;
1968                                 //ipp_do_blit(&ipp_req);
1969                                 ipp_blit_sync(&ipp_req);
1970                                 fbprintk("yaddr=0x%x,uvaddr=0x%x\n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
1971                                 yuv_phy[0] = ipp_req.dst0.YrgbMst;
1972                                 yuv_phy[1] = ipp_req.dst0.CbrMst;        
1973                                 fix->smem_start = yuv_phy[0];
1974                                 fix->mmio_start = yuv_phy[1];
1975                         }
1976                 else
1977                         {
1978                         
1979                                 fix->smem_start = yuv_phy[0];
1980                                 fix->mmio_start = yuv_phy[1];
1981                         }
1982                         
1983                 LcdWrReg(inf, WIN0_YRGB_MST, yuv_phy[0]);
1984                 LcdWrReg(inf, WIN0_CBR_MST, yuv_phy[1]);
1985                 // enable win0 after the win0 par is seted
1986                 LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(par->par_seted && par->addr_seted));
1987                 par->addr_seted = 1;
1988                 LcdWrReg(inf, REG_CFG_DONE, 0x01);
1989                 if(par->addr_seted ) {
1990                 unsigned long flags;
1991
1992                 local_irq_save(flags);
1993                 par->mirror.y_offset = yuv_phy[0];
1994                 par->mirror.c_offset = yuv_phy[1];
1995                 local_irq_restore(flags);
1996
1997                 mcu_refresh(inf);
1998                 //printk("0x%.8x 0x%.8x mirror\n", par->mirror.y_offset, par->mirror.c_offset);
1999                 }
2000
2001         }
2002
2003     has_set_rotate = false;
2004 #endif
2005     return 0;
2006 }
2007
2008 static int fb1_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2009 {
2010     struct win0_par *par = info->par;
2011      // enable win0 after the win0 addr is seted
2012
2013     win0_pan(info);
2014     par->par_seted = 1;
2015     return 0;
2016 }
2017
2018 int fb1_open(struct fb_info *info, int user)
2019 {
2020     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
2021     struct win0_par *par = info->par;
2022
2023     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
2024
2025     par->par_seted = 0;
2026     par->addr_seted = 0;
2027     inf->video_mode = 1;
2028     wq_condition2 = 1;
2029 #ifdef CONFIG_FB_ROTATE_VIDEO
2030    //reinitialize  the var when open,zyc
2031     last_yuv_phy[0] = 0;
2032     last_yuv_phy[1] = 0;
2033     has_set_rotate = 0;
2034 #endif
2035     if(par->refcount) {
2036         printk(">>>>>> fb1 has opened! \n");
2037         return -EACCES;
2038     } else {
2039         par->refcount++;
2040         fb0_set_par(inf->fb0);
2041         fb0_pan_display(&inf->fb0->var, inf->fb0);
2042         win0_blank(FB_BLANK_POWERDOWN, info);
2043         return 0;
2044     }
2045 }
2046
2047 int fb1_release(struct fb_info *info, int user)
2048 {
2049     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
2050     struct win0_par *par = info->par;
2051         struct fb_var_screeninfo *var0 = &info->var;
2052
2053     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
2054     if(inf->setFlag == 0)
2055     {
2056         wait_event_interruptible_timeout(wq, inf->setFlag, HZ*10);
2057     } 
2058     if(par->refcount) {
2059         par->refcount--;
2060         inf->video_mode = 0;
2061         par->par_seted = 0;
2062         par->addr_seted = 0;
2063         //win0_blank(FB_BLANK_POWERDOWN, info);
2064         fb0_set_par(inf->fb0);
2065         fb0_pan_display(&inf->fb0->var, inf->fb0);
2066         win1_blank(FB_BLANK_POWERDOWN, info);
2067         // wait for lcdc stop access memory
2068         //msleep(50);
2069
2070         // unmap memory
2071         info->screen_base = 0;
2072         info->fix.smem_start = 0;
2073         info->fix.smem_len = 0;
2074                 // clean the var param
2075                 memset(var0, 0, sizeof(struct fb_var_screeninfo));
2076     }
2077
2078     return 0;
2079 }
2080
2081 static int fb1_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2082 {
2083     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
2084     struct win0_par *par = info->par;
2085     struct fb_fix_screeninfo *fix0 = &info->fix;
2086     struct fb_var_screeninfo *var = &info->var;
2087     void __user *argp = (void __user *)arg;
2088     
2089 #ifdef CONFIG_FB_ROTATE_VIDEO   
2090      struct rk29fb_screen *screen = inf->cur_screen;
2091      struct rk29_ipp_req ipp_req;
2092      static u32 dstoffset = 0;
2093      
2094 #endif
2095
2096         fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
2097     fbprintk("win0fb_ioctl cmd = %8x, arg = %8x \n", (u32)cmd, (u32)arg);
2098
2099         CHK_SUSPEND(inf);
2100
2101     switch(cmd)
2102     {
2103     case FB1_IOCTL_GET_PANEL_SIZE:    //get panel size
2104         {
2105             u32 panel_size[2];
2106              if((var->rotate == 270)||(var->rotate == 90)) {
2107                 panel_size[0] = inf->panel1_info.y_res; //inf->cur_screen->y_res; change for hdmi video size
2108                 panel_size[1] = inf->panel1_info.x_res;
2109             } else {
2110                 panel_size[0] = inf->panel1_info.x_res;
2111                 panel_size[1] = inf->panel1_info.y_res;
2112             }
2113
2114             if(copy_to_user(argp, panel_size, 8))  return -EFAULT;
2115         }
2116         break;
2117
2118     case FB1_IOCTL_SET_YUV_ADDR:    //set y&uv address to register direct
2119         {
2120             u32 yuv_phy[2];
2121             if (copy_from_user(yuv_phy, argp, 8))
2122                             return -EFAULT;
2123 #ifdef CONFIG_FB_ROTATE_VIDEO 
2124                 //add by zyc
2125                 if(has_set_rotate == true)
2126                 break;
2127                 last_yuv_phy[0] = yuv_phy[0];
2128                 last_yuv_phy[1] = yuv_phy[1];
2129 #endif
2130
2131             fix0->smem_start = yuv_phy[0];
2132             fix0->mmio_start = yuv_phy[1];
2133             yuv_phy[0] += par->y_offset;
2134             yuv_phy[1] += par->c_offset;
2135          
2136             #if 0
2137                 if((var->rotate == 90) ||(var->rotate == 270))
2138             #else
2139             if(var->rotate%360 != 0)
2140             #endif
2141             {
2142                 #ifdef CONFIG_FB_ROTATE_VIDEO 
2143                 dstoffset = (dstoffset+1)%2;
2144                 ipp_req.src0.fmt = 3;
2145                 ipp_req.src0.YrgbMst = yuv_phy[0];
2146                 ipp_req.src0.CbrMst = yuv_phy[1];
2147                   ipp_req.src0.w = var->xres ;
2148                 ipp_req.src0.h = var->yres ;
2149                  ipp_req.src_vir_w= (var->xres + 15) & (~15);
2150                  ipp_req.dst_vir_w=screen->x_res;
2151
2152                 ipp_req.dst0.fmt = 3;
2153                 ipp_req.dst0.YrgbMst = inf->fb0->fix.mmio_start + screen->x_res*screen->y_res*2*dstoffset;
2154                 ipp_req.dst0.CbrMst = inf->fb0->fix.mmio_start + screen->x_res*screen->y_res*(2*dstoffset+1);
2155              //   if(var->xres > screen->x_res)
2156              //   {
2157                     ipp_req.dst0.w = screen->x_res;
2158                     ipp_req.dst0.h = screen->y_res;
2159               //  }   else  {
2160               //      ipp_req.dst0.w = var->yres;
2161              //       ipp_req.dst0.h = var->xres;
2162              //   }
2163                // ipp_req.src_vir_w = ipp_req.src0.w;
2164                // ipp_req.dst_vir_w = ipp_req.dst0.w;
2165                 ipp_req.timeout = 100;
2166                 if(var->rotate == 90)
2167                     ipp_req.flag = IPP_ROT_90;
2168                 else if(var->rotate == 180)
2169                     ipp_req.flag = IPP_ROT_180;
2170                 else if(var->rotate == 270)
2171                     ipp_req.flag = IPP_ROT_270;
2172                 //ipp_do_blit(&ipp_req);
2173                 ipp_blit_sync(&ipp_req);
2174                 fbprintk("yaddr=0x%x,uvaddr=0x%x\n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
2175                 yuv_phy[0] = ipp_req.dst0.YrgbMst;
2176                 yuv_phy[1] = ipp_req.dst0.CbrMst;    
2177                 fix0->smem_start = yuv_phy[0];
2178                 fix0->mmio_start = yuv_phy[1];
2179                 #else //CONFIG_FB_ROTATE_VIDEO
2180                 printk("LCDC not support rotate!\n");
2181                 #endif
2182             }
2183       
2184             LcdWrReg(inf, WIN0_YRGB_MST, yuv_phy[0]);
2185             LcdWrReg(inf, WIN0_CBR_MST, yuv_phy[1]);
2186             // enable win0 after the win0 par is seted
2187             LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(par->par_seted && par->addr_seted));
2188             par->addr_seted = 1;
2189             LcdWrReg(inf, REG_CFG_DONE, 0x01);
2190             if(par->par_seted) {
2191                 unsigned long flags;
2192
2193                 local_irq_save(flags);
2194                 par->mirror.y_offset = yuv_phy[0];
2195                 par->mirror.c_offset = yuv_phy[1];
2196                 local_irq_restore(flags);
2197
2198                 mcu_refresh(inf);
2199                 //printk("0x%.8x 0x%.8x mirror\n", par->mirror.y_offset, par->mirror.c_offset);
2200             }
2201         }
2202         break;
2203
2204     case FB1_IOCTL_SET_ROTATE:    //change MCU panel scan direction
2205         fbprintk(">>>>>> change lcdc direction(%d) \n", (int)arg);
2206       #ifdef CONFIG_FB_ROTATE_VIDEO 
2207                 //zyc add
2208         has_set_rotate = true;
2209         if(arg == 0 || arg==180)
2210             var->rotate = arg;    
2211         else if (arg == 90 || arg==270)
2212             var->rotate = arg;  
2213       #else //CONFIG_FB_ROTATE_VIDEO
2214         printk("LCDC not support rotate!\n");
2215       #endif
2216         break;
2217     case FB1_IOCTL_SET_WIN0_TOP:
2218         fbprintk(">>>>>> FB1_IOCTL_SET_WIN0_TOP %d\n",arg);
2219         LcdMskReg(inf, DSP_CTRL0, m_W0_ON_TOP, v_W0_ON_TOP(arg));
2220         LcdWrReg(inf, REG_CFG_DONE, 0x01);
2221         break;
2222     default:
2223         break;
2224     }
2225     return 0;
2226 }
2227
2228 static struct fb_ops fb1_ops = {
2229         .owner          = THIS_MODULE,
2230         .fb_open    = fb1_open,
2231         .fb_release = fb1_release,
2232         .fb_check_var   = fb1_check_var,
2233         .fb_set_par     = fb1_set_par,
2234         .fb_blank       = fb1_blank,
2235     .fb_pan_display = fb1_pan_display,
2236     .fb_ioctl = fb1_ioctl,
2237         .fb_setcolreg   = fb_setcolreg,
2238         .fb_fillrect    = cfb_fillrect,
2239         .fb_copyarea    = cfb_copyarea,
2240         .fb_imageblit   = cfb_imageblit,
2241 };
2242
2243 static struct fb_ops fb0_ops = {
2244         .owner          = THIS_MODULE,
2245         .fb_check_var   = fb0_check_var,
2246         .fb_set_par = fb0_set_par,
2247         .fb_blank   = fb0_blank,
2248         .fb_pan_display = fb0_pan_display,
2249     .fb_ioctl = fb0_ioctl,
2250         .fb_setcolreg   = fb_setcolreg,
2251         .fb_fillrect    = cfb_fillrect,
2252         .fb_copyarea    = cfb_copyarea,
2253         .fb_imageblit   = cfb_imageblit,
2254         //.fb_cursor      = rk29_set_cursor,
2255 };
2256
2257 int fb_get_video_mode(void)
2258 {
2259         struct rk29fb_inf *inf;
2260         if(!g_pdev)
2261                 return 0;
2262         inf = platform_get_drvdata(g_pdev);
2263         return inf->video_mode;
2264 }
2265 /*
2266 enable: 1, switch to tv or hdmi; 0, switch to lcd
2267 */
2268 int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable )
2269 {
2270     struct rk29fb_inf *inf = platform_get_drvdata(g_pdev);
2271    // struct rk29fb_info *mach_info = g_pdev->dev.platform_data;
2272     struct rk29fb_info *mach_info = g_pdev->dev.platform_data;
2273
2274     memcpy(&inf->panel2_info, screen, sizeof( struct rk29fb_screen ));
2275
2276     if(enable)inf->cur_screen = &inf->panel2_info;
2277     else inf->cur_screen = &inf->panel1_info;
2278
2279     /* Black out, because some display device need clock to standby */
2280     //LcdMskReg(inf, DSP_CTRL_REG1, m_BLACK_OUT, v_BLACK_OUT(1));
2281    // LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(0));
2282    // LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0));
2283     LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE,  v_BLACK_MODE(1));
2284     LcdWrReg(inf, REG_CFG_DONE, 0x01);
2285     wake_lock(&idlelock);
2286     msleep(20);
2287     wake_unlock(&idlelock);
2288
2289     if(inf->cur_screen->standby)    inf->cur_screen->standby(1);
2290     // operate the display_on pin to power down the lcd
2291    
2292     if(enable && mach_info->io_disable)mach_info->io_disable();  //close lcd out
2293     else if (mach_info->io_enable)mach_info->io_enable();       //open lcd out
2294     
2295     load_screen(inf->fb0, 0);
2296         mcu_refresh(inf);
2297
2298     fb1_set_par(inf->fb1);
2299     fb0_set_par(inf->fb0);
2300     LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE,  v_BLACK_MODE(0));
2301     LcdWrReg(inf, REG_CFG_DONE, 0x01);
2302     return 0;
2303 }
2304
2305 static ssize_t dsp_win0_info_read(struct device *device,
2306                             struct device_attribute *attr, char *buf)
2307 {
2308     //char * s = _buf;
2309     struct rk29fb_inf *inf = platform_get_drvdata(g_pdev);
2310     struct rk29fb_screen *screen = inf->cur_screen;
2311
2312     u16 xpos=0,ypos=0,xsize=0,ysize=0;
2313
2314     fbprintk("%s\n",__FUNCTION__);
2315     xpos = LcdRdReg(inf, WIN0_DSP_ST) & 0xffff;
2316     ypos = (LcdRdReg(inf, WIN0_DSP_ST)>>16) & 0xffff;
2317
2318     xpos -= (screen->left_margin + screen->hsync_len);
2319     ypos -= (screen->upper_margin + screen->vsync_len);
2320
2321     xsize=LcdRdReg(inf, WIN0_DSP_INFO)& 0xffff;
2322     ysize=(LcdRdReg(inf, WIN0_DSP_INFO)>>16) & 0xffff;
2323     fbprintk("%s %d , %d, %d ,%d\n",__FUNCTION__,xpos,ypos,xsize,ysize);
2324         rk29_set_cursor_test(inf->fb0);
2325
2326     return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n", xpos,ypos,xsize,ysize);
2327 }
2328
2329 static ssize_t dsp_win0_info_write(struct device *device,
2330                            struct device_attribute *attr, const char *buf, size_t count)
2331 {
2332      printk("%s\n",__FUNCTION__);
2333      printk("%s %x \n",__FUNCTION__,*buf);
2334      return count;
2335 }
2336
2337 static DEVICE_ATTR(dsp_win0_info,  S_IRUGO|S_IWUSR, dsp_win0_info_read, dsp_win0_info_write);
2338
2339 static irqreturn_t rk29fb_irq(int irq, void *dev_id)
2340 {
2341         struct platform_device *pdev = (struct platform_device*)dev_id;
2342     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
2343     struct win0_par *par = (struct win0_par *)inf->fb1->par;
2344     if(!inf)
2345         return IRQ_HANDLED;
2346
2347         //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
2348
2349     LcdMskReg(inf, INT_STATUS, m_FRM_STARTCLEAR, v_FRM_STARTCLEAR(1));
2350
2351         if(SCREEN_MCU == inf->cur_screen->type)
2352         {
2353         inf->mcu_isrcnt = !inf->mcu_isrcnt;
2354         if(inf->mcu_isrcnt)
2355             return IRQ_HANDLED;
2356
2357         if(IsMcuUseFmk())
2358         {
2359             if(LcdReadBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_FRAME_ST) && (inf->mcu_fmksync == 0))
2360             {
2361                 inf->mcu_fmksync = 1;
2362                  if(inf->cur_screen->refresh)
2363                    inf->cur_screen->refresh(REFRESH_END);
2364                 inf->mcu_fmksync = 0;
2365             }
2366             else
2367             {
2368                 return IRQ_HANDLED;
2369             }
2370         }
2371         else
2372         {
2373             if(inf->mcu_needflush) {
2374                 if(inf->cur_screen->refresh)
2375                     inf->cur_screen->refresh(REFRESH_PRE);
2376                 inf->mcu_needflush = 0;
2377                 inf->mcu_isrcnt = 0;
2378                 LcdSetRegisterBit(inf, MCU_TIMING_CTRL, m_MCU_HOLDMODE_FRAME_ST);
2379             } else {
2380                 if(inf->cur_screen->refresh)
2381                     inf->cur_screen->refresh(REFRESH_END);
2382             }
2383         }
2384         }
2385 #if ANDROID_USE_THREE_BUFS
2386     new_frame_seted = 1;
2387 #endif
2388
2389     if(waitqueue_active(&par->wait)) {
2390         if (par->mirror.c_offset == 0)
2391             printk("error: no new buffer to display\n");
2392
2393         par->done.y_offset = par->displ.y_offset;
2394         par->done.c_offset = par->displ.c_offset;
2395         par->displ.y_offset = par->mirror.y_offset;
2396         par->displ.c_offset = par->mirror.c_offset;
2397         par->mirror.y_offset = 0;
2398         par->mirror.c_offset = 0;
2399
2400         //printk("0x%.8x 0x%.8x displaying\n", par->displ.y_offset, par->displ.c_offset);
2401         //printk("0x%.8x 0x%.8x done\n", par->done.y_offset, par->done.c_offset);
2402         wake_up_interruptible(&par->wait);
2403     }
2404
2405     wq_condition2 = 1;
2406         wq_condition = 1;
2407         wake_up_interruptible(&wq);
2408
2409         rk29fb_irq_notify_ddr();
2410         return IRQ_HANDLED;
2411 }
2412
2413 #ifdef CONFIG_HAS_EARLYSUSPEND
2414
2415 struct suspend_info {
2416         struct early_suspend early_suspend;
2417         struct rk29fb_inf *inf;
2418 };
2419
2420 static void rk29fb_early_suspend(struct early_suspend *h)
2421 {
2422         struct suspend_info *info = container_of(h, struct suspend_info,
2423                                                 early_suspend);
2424
2425     struct rk29fb_inf *inf = info->inf;
2426     struct rk29fb_info *mach_info = g_pdev->dev.platform_data;
2427
2428     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
2429
2430     if(!inf) {
2431         printk("inf==0, rk29fb_suspend fail! \n");
2432         return;
2433     }
2434
2435     if((inf->cur_screen != &inf->panel2_info) && mach_info->io_disable)  // close lcd pwr when output screen is lcd
2436        mach_info->io_disable();  //close lcd out 
2437
2438         if(inf->cur_screen->standby)
2439         {
2440                 fbprintk(">>>>>> power down the screen! \n");
2441                 inf->cur_screen->standby(1);
2442         }
2443
2444     LcdMskReg(inf, DSP_CTRL0, m_HSYNC_POLARITY | m_VSYNC_POLARITY | m_DEN_POLARITY ,
2445        v_HSYNC_POLARITY(1) | v_VSYNC_POLARITY(1) | v_DEN_POLARITY(1) );
2446
2447     LcdMskReg(inf, DSP_CTRL1, m_BLANK_MODE , v_BLANK_MODE(1));
2448     LcdMskReg(inf, SYS_CONFIG, m_STANDBY, v_STANDBY(1));
2449         LcdWrReg(inf, REG_CFG_DONE, 0x01);
2450
2451         if(!inf->in_suspend)
2452         {
2453                 fbprintk(">>>>>> diable the lcdc clk! \n");
2454                 wake_lock(&idlelock);
2455                 msleep(100);
2456                 wake_unlock(&idlelock);
2457         clk_disable(inf->aclk_ddr_lcdc);
2458         clk_disable(inf->aclk_disp_matrix);
2459         clk_disable(inf->hclk_cpu_display);
2460         clk_disable(inf->clk);
2461         if (inf->dclk){
2462             clk_disable(inf->dclk);
2463         }
2464         if(inf->clk){
2465             clk_disable(inf->aclk);
2466         }
2467         clk_disable(inf->pd_display);
2468
2469                 inf->in_suspend = 1;
2470         }
2471 }
2472
2473 static void rk29fb_early_resume(struct early_suspend *h)
2474 {
2475         struct suspend_info *info = container_of(h, struct suspend_info,
2476                                         early_suspend);
2477
2478     struct rk29fb_inf *inf = info->inf;
2479     struct rk29fb_screen *screen = inf->cur_screen;
2480     struct rk29fb_info *mach_info = g_pdev->dev.platform_data;
2481
2482     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
2483     if(!inf) {
2484         printk("inf==0, rk29fb_resume fail! \n");
2485         return ;
2486     }
2487
2488     if(inf->in_suspend)
2489         {
2490             inf->in_suspend = 0;
2491         fbprintk(">>>>>> enable the lcdc clk! \n");
2492         clk_enable(inf->pd_display);
2493         clk_enable(inf->aclk_disp_matrix);
2494         clk_enable(inf->hclk_cpu_display);
2495         clk_enable(inf->clk);
2496         clk_enable(inf->aclk_ddr_lcdc);
2497
2498         if (inf->dclk){
2499             clk_enable(inf->dclk);
2500         }
2501         if(inf->clk){
2502             clk_enable(inf->aclk);
2503         }
2504         msleep(100);
2505         }
2506     LcdMskReg(inf, DSP_CTRL1, m_BLANK_MODE , v_BLANK_MODE(0));
2507     LcdMskReg(inf, SYS_CONFIG, m_STANDBY, v_STANDBY(0));
2508     LcdWrReg(inf, REG_CFG_DONE, 0x01);
2509
2510     LcdMskReg(inf, DSP_CTRL0, m_HSYNC_POLARITY | m_VSYNC_POLARITY | m_DEN_POLARITY ,
2511        v_HSYNC_POLARITY(screen->pin_hsync) | v_VSYNC_POLARITY(screen->pin_vsync) | v_DEN_POLARITY(screen->pin_den) );
2512
2513         if(inf->cur_screen->standby)
2514         {
2515                 fbprintk(">>>>>> power on the screen! \n");
2516                 inf->cur_screen->standby(0);
2517         }
2518     msleep(10);
2519     memcpy((u8*)inf->preg, (u8*)&inf->regbak, 0xa4);  //resume reg
2520     msleep(40);
2521     
2522     if((inf->cur_screen != &inf->panel2_info) && mach_info->io_enable)  // open lcd pwr when output screen is lcd
2523        mach_info->io_enable();  //close lcd out 
2524         
2525 }
2526
2527 static struct suspend_info suspend_info = {
2528         .early_suspend.suspend = rk29fb_early_suspend,
2529         .early_suspend.resume = rk29fb_early_resume,
2530         .early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
2531 };
2532 #endif
2533 struct fb_info *g_fb0_inf = NULL;  //add cym@rk 20101027 for charger logo
2534 static int __devinit rk29fb_probe (struct platform_device *pdev)
2535 {
2536     struct rk29fb_inf *inf = NULL;
2537     struct resource *res = NULL;
2538     struct resource *mem = NULL;
2539     struct rk29fb_info *mach_info = NULL;
2540     struct rk29fb_screen *screen = NULL;
2541     struct win0_par* par = NULL;
2542         int irq = 0;
2543     int ret = 0;
2544
2545     fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
2546
2547     /* Malloc rk29fb_inf and set it to pdev for drvdata */
2548     fbprintk(">> Malloc rk29fb_inf and set it to pdev for drvdata \n");
2549     inf = kmalloc(sizeof(struct rk29fb_inf), GFP_KERNEL);
2550     if(!inf)
2551     {
2552         dev_err(&pdev->dev, ">> inf kmalloc fail!");
2553         ret = -ENOMEM;
2554                 goto release_drvdata;
2555     }
2556     memset(inf, 0, sizeof(struct rk29fb_inf));
2557         platform_set_drvdata(pdev, inf);
2558
2559     mach_info = pdev->dev.platform_data;
2560     /* Fill screen info and set current screen */
2561     fbprintk(">> Fill screen info and set current screen \n");
2562    #ifdef CONFIG_DEFAULT_OUT_HDMI  // set hdmi for default output 
2563     hdmi_get_default_resolution(&inf->panel1_info);
2564    #else
2565     set_lcd_info(&inf->panel1_info, mach_info->lcd_info);
2566    #endif
2567     inf->cur_screen = &inf->panel1_info;
2568     screen = inf->cur_screen;
2569     if(SCREEN_NULL==screen->type)
2570     {
2571         dev_err(&pdev->dev, ">> Please select a display device! \n");
2572         ret = -EINVAL;
2573                 goto release_drvdata;
2574     }
2575
2576     /* get virtual basic address of lcdc register */
2577     fbprintk(">> get virtual basic address of lcdc register \n");
2578     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcdc reg");
2579     if (res == NULL)
2580     {
2581         dev_err(&pdev->dev, "failed to get memory registers\n");
2582         ret = -ENOENT;
2583                 goto release_drvdata;
2584     }
2585     inf->reg_phy_base = res->start;
2586     inf->len = (res->end - res->start) + 1;
2587     mem = request_mem_region(inf->reg_phy_base, inf->len, pdev->name);
2588     if (mem == NULL)
2589     {
2590         dev_err(&pdev->dev, "failed to get memory region\n");
2591         ret = -ENOENT;
2592                 goto release_drvdata;
2593     }
2594     fbprintk("inf->reg_phy_base = 0x%08x, inf->len = %d \n", inf->reg_phy_base, inf->len);
2595     inf->reg_vir_base = ioremap(inf->reg_phy_base, inf->len);
2596     if (inf->reg_vir_base == NULL)
2597     {
2598         dev_err(&pdev->dev, "ioremap() of registers failed\n");
2599         ret = -ENXIO;
2600                 goto release_drvdata;
2601     }
2602     inf->preg = (LCDC_REG*)inf->reg_vir_base;
2603
2604     /* Prepare win1 info */
2605     fbprintk(">> Prepare win1 info \n");
2606         inf->fb0 = framebuffer_alloc(sizeof(struct win0_par), &pdev->dev);
2607     if(!inf->fb0)
2608     {
2609         dev_err(&pdev->dev, ">> fb0 framebuffer_alloc fail!");
2610                 inf->fb0 = NULL;
2611         ret = -ENOMEM;
2612                 goto release_win1fb;
2613     }
2614
2615     par = (struct win0_par*)inf->fb0->par;
2616     strcpy(inf->fb0->fix.id, "fb0");
2617     inf->fb0->fix.type        = FB_TYPE_PACKED_PIXELS;
2618     inf->fb0->fix.type_aux    = 0;
2619     inf->fb0->fix.xpanstep    = 1;
2620     inf->fb0->fix.ypanstep    = 1;
2621     inf->fb0->fix.ywrapstep   = 0;
2622     inf->fb0->fix.accel       = FB_ACCEL_NONE;
2623     inf->fb0->fix.visual      = FB_VISUAL_TRUECOLOR;
2624     inf->fb0->fix.smem_len    = 0;
2625     inf->fb0->fix.line_length = 0;
2626     inf->fb0->fix.smem_start  = 0;
2627
2628     inf->fb0->var.xres = screen->x_res;
2629     inf->fb0->var.yres = screen->y_res;
2630     inf->fb0->var.bits_per_pixel = 16;
2631     inf->fb0_color_deepth = 0;
2632     inf->fb0->var.xres_virtual = screen->x_res;
2633     inf->fb0->var.yres_virtual = screen->y_res;
2634     inf->fb0->var.width = screen->width;
2635     inf->fb0->var.height = screen->height;
2636     inf->fb0->var.pixclock = screen->pixclock;
2637     inf->fb0->var.left_margin = screen->left_margin;
2638     inf->fb0->var.right_margin = screen->right_margin;
2639     inf->fb0->var.upper_margin = screen->upper_margin;
2640     inf->fb0->var.lower_margin = screen->lower_margin;
2641     inf->fb0->var.vsync_len = screen->vsync_len;
2642     inf->fb0->var.hsync_len = screen->hsync_len;
2643     inf->fb0->var.red    = def_rgb_16.red;
2644     inf->fb0->var.green  = def_rgb_16.green;
2645     inf->fb0->var.blue   = def_rgb_16.blue;
2646     inf->fb0->var.transp = def_rgb_16.transp;
2647
2648     inf->fb0->var.nonstd      = 0;  //win1 format & ypos & xpos (ypos<<20 + xpos<<8 + format)
2649     inf->fb0->var.grayscale   = 0;  //win1 transprent mode & value(mode<<8 + value)
2650     inf->fb0->var.activate    = FB_ACTIVATE_NOW;
2651     inf->fb0->var.accel_flags = 0;
2652     inf->fb0->var.vmode       = FB_VMODE_NONINTERLACED;
2653
2654     inf->fb0->fbops           = &fb0_ops;
2655     inf->fb0->flags           = FBINFO_FLAG_DEFAULT;
2656     inf->fb0->pseudo_palette  = par->pseudo_pal;
2657     inf->fb0->screen_base     = 0;
2658
2659     memset(par, 0, sizeof(struct win0_par));
2660
2661         ret = fb_alloc_cmap(&inf->fb0->cmap, 256, 0);
2662         if (ret < 0)
2663                 goto release_cmap;
2664
2665         g_fb0_inf = inf->fb0; //add cym@rk 20101027
2666
2667     /* alloc win1 buf */
2668     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "win1 buf");
2669     if (res == NULL)
2670     {
2671         dev_err(&pdev->dev, "failed to get win1 memory \n");
2672         ret = -ENOENT;
2673         goto release_win1fb;
2674     }
2675     inf->fb0->fix.smem_start = res->start;
2676     inf->fb0->fix.smem_len = res->end - res->start + 1;
2677     inf->fb0->screen_base = ioremap(res->start, inf->fb0->fix.smem_len);
2678     memset(inf->fb0->screen_base, 0, inf->fb0->fix.smem_len);
2679
2680     #ifdef CONFIG_FB_WORK_IPP
2681        /* alloc win1 ipp buf */
2682     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "win1 ipp buf");
2683     if (res == NULL)
2684     {
2685         dev_err(&pdev->dev, "failed to get win1 ipp memory \n");
2686         ret = -ENOENT;
2687         goto release_win1fb;
2688     }
2689     inf->fb0->fix.mmio_start = res->start;
2690     inf->fb0->fix.mmio_len = res->end - res->start + 1;
2691     #endif
2692
2693     /* Prepare win0 info */
2694     fbprintk(">> Prepare win0 info \n");
2695     inf->fb1 = framebuffer_alloc(sizeof(struct win0_par), &pdev->dev);
2696     if(!inf->fb1)
2697     {
2698         dev_err(&pdev->dev, ">> fb1 framebuffer_alloc fail!");
2699                 inf->fb1 = NULL;
2700                 ret = -ENOMEM;
2701                 goto release_win0fb;
2702     }
2703
2704     par = (struct win0_par*)inf->fb1->par;
2705
2706     strcpy(inf->fb1->fix.id, "fb1");
2707         inf->fb1->fix.type            = FB_TYPE_PACKED_PIXELS;
2708         inf->fb1->fix.type_aux    = 0;
2709         inf->fb1->fix.xpanstep    = 1;
2710         inf->fb1->fix.ypanstep    = 1;
2711         inf->fb1->fix.ywrapstep   = 0;
2712         inf->fb1->fix.accel       = FB_ACCEL_NONE;
2713     inf->fb1->fix.visual      = FB_VISUAL_TRUECOLOR;
2714     inf->fb1->fix.smem_len    = 0;
2715     inf->fb1->fix.line_length = 0;
2716     inf->fb1->fix.smem_start  = 0;
2717
2718     inf->fb1->var.xres = screen->x_res;
2719     inf->fb1->var.yres = screen->y_res;
2720     inf->fb1->var.bits_per_pixel = 16;
2721     inf->fb1->var.xres_virtual = screen->x_res;
2722     inf->fb1->var.yres_virtual = screen->y_res;
2723     inf->fb1->var.width = screen->width;
2724     inf->fb1->var.height = screen->height;
2725     inf->fb1->var.pixclock = screen->pixclock;
2726     inf->fb1->var.left_margin = screen->left_margin;
2727     inf->fb1->var.right_margin = screen->right_margin;
2728     inf->fb1->var.upper_margin = screen->upper_margin;
2729     inf->fb1->var.lower_margin = screen->lower_margin;
2730     inf->fb1->var.vsync_len = screen->vsync_len;
2731     inf->fb1->var.hsync_len = screen->hsync_len;
2732     inf->fb1->var.red    = def_rgb_16.red;
2733     inf->fb1->var.green  = def_rgb_16.green;
2734     inf->fb1->var.blue   = def_rgb_16.blue;
2735     inf->fb1->var.transp = def_rgb_16.transp;
2736
2737     inf->fb1->var.nonstd      = 0;  //win0 format & ypos & xpos (ypos<<20 + xpos<<8 + format)
2738     inf->fb1->var.grayscale   = ((inf->fb1->var.yres<<20)&0xfff00000) + ((inf->fb1->var.xres<<8)&0xfff00);//win0 xsize & ysize
2739     inf->fb1->var.activate    = FB_ACTIVATE_NOW;
2740     inf->fb1->var.accel_flags = 0;
2741     inf->fb1->var.vmode       = FB_VMODE_NONINTERLACED;
2742
2743     inf->fb1->fbops           = &fb1_ops;
2744         inf->fb1->flags               = FBINFO_FLAG_DEFAULT;
2745         inf->fb1->pseudo_palette  = par->pseudo_pal;
2746         inf->fb1->screen_base     = 0;
2747
2748     memset(par, 0, sizeof(struct win0_par));
2749
2750         init_waitqueue_head(&par->wait);
2751
2752         /* Init all lcdc and lcd before register_framebuffer. */
2753         /* because after register_framebuffer, the win1fb_check_par and winfb_set_par execute immediately */
2754         fbprintk(">> Init all lcdc and lcd before register_framebuffer \n");
2755     init_lcdc(inf->fb0);
2756
2757   #if 0 //def CONFIG_CPU_FREQ
2758    // inf->freq_transition.notifier_call = rk29fb_freq_transition;
2759    // cpufreq_register_notifier(&inf->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
2760   #endif
2761         fbprintk("got clock\n");
2762
2763         if(mach_info)
2764     {
2765         struct rk29_fb_setting_info fb_setting;
2766         if( OUT_P888==inf->cur_screen->face )     // set lcdc iomux
2767         {
2768             fb_setting.data_num = 24;
2769         }
2770         else if(OUT_P666 == inf->cur_screen->face )
2771         {
2772             fb_setting.data_num = 18;
2773         }
2774         else
2775         {
2776             fb_setting.data_num = 16;
2777         }
2778         fb_setting.den_en = 1;
2779         fb_setting.vsync_en = 1;
2780         fb_setting.disp_on_en = 1;
2781         fb_setting.standby_en = 1;
2782         if( inf->cur_screen->mcu_usefmk )
2783             fb_setting.mcu_fmk_en =1;
2784         mach_info->io_init(&fb_setting);
2785     }
2786
2787         //set_lcd_pin(pdev, 1);
2788         mdelay(10);
2789         g_pdev = pdev;
2790         inf->mcu_usetimer = 1;
2791     inf->mcu_fmksync = 0;
2792         load_screen(inf->fb0, 1);
2793
2794     /* Register framebuffer(fb0 & fb1) */
2795     fbprintk(">> Register framebuffer(fb0) \n");
2796     ret = register_framebuffer(inf->fb0);
2797     if(ret<0)
2798     {
2799         printk(">> fb0 register_framebuffer fail!\n");
2800         ret = -EINVAL;
2801                 goto release_win0fb;
2802     }
2803     fbprintk(">> Register framebuffer(fb1) \n");
2804
2805     ret = register_framebuffer(inf->fb1);
2806     if(ret<0)
2807     {
2808         printk(">> fb1 register_framebuffer fail!\n");
2809         ret = -EINVAL;
2810                 goto unregister_win1fb;
2811     }
2812
2813     ret = device_create_file(inf->fb1->dev, &dev_attr_dsp_win0_info);
2814     if(ret)
2815     {
2816         printk(">> fb1 dsp win0 info device_create_file err\n");
2817         ret = -EINVAL;
2818     }
2819 #ifdef CONFIG_HAS_EARLYSUSPEND
2820         suspend_info.inf = inf;
2821         register_early_suspend(&suspend_info.early_suspend);
2822 #endif
2823
2824     /* get and request irq */
2825     fbprintk(">> get and request irq \n");
2826     irq = platform_get_irq(pdev, 0);
2827     if (irq < 0) {
2828         dev_err(&pdev->dev, "no irq for device\n");
2829         ret = -ENOENT;
2830         goto unregister_win1fb;
2831     }
2832     ret = request_irq(irq, rk29fb_irq, IRQF_DISABLED, pdev->name, pdev);
2833     if (ret) {
2834         dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
2835         ret = -EBUSY;
2836         goto release_irq;
2837     }
2838
2839     if( inf->cur_screen->mcu_usefmk && (mach_info->mcu_fmk_pin != -1) )
2840     {
2841         ret = request_irq(gpio_to_irq(mach_info->mcu_fmk_pin), mcu_irqfmk, GPIOEdgelFalling, pdev->name, pdev);
2842         if (ret)
2843         {
2844             dev_err(&pdev->dev, "cannot get fmk irq %d - err %d\n", irq, ret);
2845             ret = -EBUSY;
2846             goto release_irq;
2847         }
2848     }
2849
2850 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
2851     fb0_set_par(inf->fb0);
2852     if (fb_prepare_logo(inf->fb0, FB_ROTATE_UR)) {
2853         /* Start display and show logo on boot */
2854         fb_set_cmap(&inf->fb0->cmap, inf->fb0);
2855         fb_show_logo(inf->fb0, FB_ROTATE_UR);
2856         fb0_blank(FB_BLANK_UNBLANK, inf->fb0);
2857     }
2858 #endif
2859
2860     printk(" %s ok\n", __FUNCTION__);
2861     return ret;
2862
2863 release_irq:
2864         if(irq>=0)
2865         free_irq(irq, pdev);
2866 unregister_win1fb:
2867     unregister_framebuffer(inf->fb0);
2868 release_win0fb:
2869         if(inf->fb1)
2870                 framebuffer_release(inf->fb1);
2871         inf->fb1 = NULL;
2872 release_cmap:
2873     if(&inf->fb0->cmap)
2874         fb_dealloc_cmap(&inf->fb0->cmap);
2875 release_win1fb:
2876         if(inf->fb0)
2877                 framebuffer_release(inf->fb0);
2878         inf->fb0 = NULL;
2879 release_drvdata:
2880         if(inf && inf->reg_vir_base)
2881         iounmap(inf->reg_vir_base);
2882         if(inf && mem)
2883         release_mem_region(inf->reg_phy_base, inf->len);
2884         if(inf)
2885         kfree(inf);
2886         platform_set_drvdata(pdev, NULL);
2887         return ret;
2888 }
2889
2890 static int __devexit rk29fb_remove(struct platform_device *pdev)
2891 {
2892     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
2893     struct fb_info *info = NULL;
2894         //pm_message_t msg;
2895     struct rk29fb_info *mach_info = NULL;
2896     int irq = 0;
2897
2898         fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
2899
2900     if(!inf) {
2901         printk("inf==0, rk29_fb_remove fail! \n");
2902         return -EINVAL;
2903     }
2904     device_remove_file(inf->fb1->dev, &dev_attr_dsp_win0_info);
2905
2906     irq = platform_get_irq(pdev, 0);
2907     if (irq >0)
2908     {
2909     free_irq(irq, pdev);
2910     }
2911
2912     mach_info = pdev->dev.platform_data;
2913     if(mach_info->mcu_fmk_pin)
2914     {
2915         free_irq(gpio_to_irq(mach_info->mcu_fmk_pin), pdev);
2916     }
2917
2918     if(mach_info->io_disable)  
2919        mach_info->io_disable();  //close lcd out 
2920
2921     // blank the lcdc
2922     if(inf->fb1)
2923         fb1_blank(FB_BLANK_POWERDOWN, inf->fb1);
2924     if(inf->fb0)
2925         fb0_blank(FB_BLANK_POWERDOWN, inf->fb0);
2926
2927         // suspend the lcdc
2928         //rk29fb_suspend(pdev, msg);
2929     // unmap memory and release framebuffer
2930     if(inf->fb1) {
2931         info = inf->fb1;
2932         if (info->screen_base) {
2933                 //dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len),info->screen_base, info->fix.smem_start);
2934                 info->screen_base = 0;
2935                 info->fix.smem_start = 0;
2936                 info->fix.smem_len = 0;
2937         }
2938         unregister_framebuffer(inf->fb1);
2939         framebuffer_release(inf->fb1);
2940         inf->fb1 = NULL;
2941     }
2942     if(inf->fb0) {
2943         info = inf->fb0;
2944         if (info->screen_base) {
2945             //    dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len),info->screen_base, info->fix.smem_start);
2946                 info->screen_base = 0;
2947                 info->fix.smem_start = 0;
2948                 info->fix.smem_len = 0;
2949         }
2950         unregister_framebuffer(inf->fb0);
2951         framebuffer_release(inf->fb0);
2952         inf->fb0 = NULL;
2953     }
2954
2955   #if 0 //def CONFIG_CPU_FREQ
2956    // cpufreq_unregister_notifier(&inf->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
2957   #endif
2958
2959     msleep(100);
2960
2961         if (inf->clk)
2962     {
2963                 clk_disable(inf->clk);
2964                 clk_put(inf->clk);
2965                 inf->clk = NULL;
2966         }
2967     if (inf->dclk)
2968     {
2969                 clk_disable(inf->dclk);
2970                 clk_put(inf->dclk);
2971                 inf->dclk = NULL;
2972         }
2973
2974     kfree(inf);
2975     platform_set_drvdata(pdev, NULL);
2976
2977     return 0;
2978 }
2979
2980 static void rk29fb_shutdown(struct platform_device *pdev)
2981 {
2982     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
2983     struct rk29fb_info *mach_info = pdev->dev.platform_data;;
2984
2985         fbprintk("----------------------------rk29fb_shutdown----------------------------\n");
2986
2987     if(mach_info->io_disable)  
2988        mach_info->io_disable();  //close lcd out 
2989        
2990     if(!inf->in_suspend)
2991     {
2992         LcdMskReg(inf, DSP_CTRL1, m_BLANK_MODE , v_BLANK_MODE(1));
2993         LcdMskReg(inf, SYS_CONFIG, m_STANDBY, v_STANDBY(1));
2994         LcdWrReg(inf, REG_CFG_DONE, 0x01);
2995         mdelay(100);
2996         clk_disable(inf->aclk_ddr_lcdc);
2997         clk_disable(inf->aclk_disp_matrix);
2998         clk_disable(inf->hclk_cpu_display);
2999         clk_disable(inf->clk);
3000         if(inf->dclk){
3001             clk_disable(inf->dclk);
3002         }
3003         if(inf->clk){
3004             clk_disable(inf->aclk);
3005         }
3006         clk_disable(inf->pd_display);
3007         //pmu_set_power_domain(PD_DISPLAY, 0);
3008                 inf->in_suspend = 1;
3009         }
3010
3011 }
3012
3013 static struct platform_driver rk29fb_driver = {
3014         .probe          = rk29fb_probe,
3015         .remove         = __devexit_p(rk29fb_remove),
3016         .driver         = {
3017                 .name   = "rk29-fb",
3018                 .owner  = THIS_MODULE,
3019         },
3020         .shutdown   = rk29fb_shutdown,
3021 };
3022
3023 static int __init rk29fb_init(void)
3024 {
3025         wake_lock_init(&idlelock, WAKE_LOCK_IDLE, "fb");
3026     return platform_driver_register(&rk29fb_driver);
3027 }
3028
3029 static void __exit rk29fb_exit(void)
3030 {
3031     platform_driver_unregister(&rk29fb_driver);
3032 }
3033
3034 fs_initcall(rk29fb_init);
3035 module_exit(rk29fb_exit);
3036
3037
3038 MODULE_AUTHOR("  zyw@rock-chips.com");
3039 MODULE_DESCRIPTION("Driver for rk29 fb device");
3040 MODULE_LICENSE("GPL");
3041
3042