rk30 fb: do not disable fb when the syscall close of fb was called
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / rk_fb.c
1 /*
2  * drivers/video/rockchip/rk_fb.c
3  *
4  * Copyright (C) 2012 ROCKCHIP, Inc.
5  *Author:yzq<yzq@rock-chips.com>
6         yxj<yxj@rock-chips.com>
7  * This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/string.h>
21 #include <linux/mm.h>
22 #include <linux/slab.h>
23 #include <linux/delay.h>
24 #include <linux/device.h>
25 #include <linux/fb.h>
26 #include <linux/init.h>
27 #include <linux/platform_device.h>
28 #include <linux/earlysuspend.h>
29 #include <asm/div64.h>
30 #include <asm/uaccess.h>
31 #include<linux/rk_fb.h>
32 #include <plat/ipp.h>
33 #include "hdmi/rk_hdmi.h"
34
35
36 #if 0
37         #define fbprintk(msg...)        printk(msg);
38 #else
39         #define fbprintk(msg...)
40 #endif
41
42 #if 1
43 #define CHK_SUSPEND(drv)        \
44         if(atomic_read(&drv->in_suspend))       {       \
45                 printk(">>>>>> fb is in suspend! return! \n");  \
46                 return -EPERM;  \
47         }
48 #else
49 #define CHK_SUSPEND(inf)
50 #endif
51
52 static struct platform_device *g_fb_pdev;
53
54 static struct rk_fb_rgb def_rgb_16 = {
55      red:    { offset: 11, length: 5, },
56      green:  { offset: 5,  length: 6, },
57      blue:   { offset: 0,  length: 5, },
58      transp: { offset: 0,  length: 0, },
59 };
60
61
62 /***************************************************************************
63 fb0-----------lcdc0------------win1  for ui
64 fb1-----------lcdc0------------win0  for video,win0 support 3d display
65 fb2-----------lcdc1------------win1  for ui
66 fb3-----------lcdc1-------------win0 for video ,win0 support 3d display
67
68 defautl:we alloc three buffer,one for fb0 and fb2 display ui,one for ipp rotate
69         fb1 and fb3 are used for video play,the buffer is alloc by android,and
70         pass the phy addr to fix.smem_start by ioctl
71 ****************************************************************************/
72
73 int get_fb_layer_id(struct fb_fix_screeninfo *fix)
74 {
75         int layer_id;
76         if(!strcmp(fix->id,"fb1")||!strcmp(fix->id,"fb3"))
77         {
78                 layer_id = 0;
79         }
80         else if(!strcmp(fix->id,"fb0")||!strcmp(fix->id,"fb2"))
81         {
82                 layer_id = 1;
83         }
84         else
85         {
86                 printk(KERN_ERR "unsupported %s",fix->id);
87                 layer_id = -ENODEV;
88         }
89
90         return layer_id;
91 }
92
93 /**********************************************************************
94 this is for hdmi
95 name: lcdc device name ,lcdc0 , lcdc1
96 ***********************************************************************/
97 struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name)
98 {
99         struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
100         int i = 0;
101         for( i = 0; i < inf->num_lcdc; i++)
102         {
103                 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
104                         break;
105         }
106         return inf->lcdc_dev_drv[i];
107         
108 }
109 static int rk_fb_open(struct fb_info *info,int user)
110 {
111     struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
112     int layer_id;
113     CHK_SUSPEND(dev_drv);
114     layer_id = get_fb_layer_id(&info->fix);
115     if(dev_drv->layer_par[layer_id]->state)
116     {
117         return 0;    // if this layer aready opened ,no need to reopen
118     }
119     else
120     {
121         dev_drv->open(dev_drv,layer_id,1);
122     }
123     
124     return 0;
125     
126 }
127
128 static int rk_fb_close(struct fb_info *info,int user)
129 {
130         /*struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
131         int layer_id;
132         CHK_SUSPEND(dev_drv);
133         layer_id = get_fb_layer_id(&info->fix);
134         if(!dev_drv->layer_par[layer_id]->state)
135         {
136                 return 0;
137         }
138         else
139         {
140                 dev_drv->open(dev_drv,layer_id,0);
141         }*/
142         
143         return 0;
144 }
145 static void fb_copy_by_ipp(struct fb_info *dst_info, struct fb_info *src_info,int offset)
146 {
147         struct rk29_ipp_req ipp_req;
148         u32 dstoffset = 0;
149         memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
150         ipp_req.src0.YrgbMst = src_info->fix.smem_start + offset;
151         ipp_req.src0.w = src_info->var.xres;
152         ipp_req.src0.h = src_info->var.yres;
153
154         ipp_req.dst0.YrgbMst = dst_info->fix.smem_start + offset;
155         ipp_req.dst0.w = src_info->var.xres;
156         ipp_req.dst0.h = src_info->var.yres;
157
158         ipp_req.src_vir_w = src_info->var.xres_virtual;
159         ipp_req.dst_vir_w = src_info->var.xres_virtual;
160         ipp_req.timeout = 100;
161         ipp_req.flag = IPP_ROT_0;
162         ipp_blit_sync(&ipp_req);
163         
164 }
165 static void hdmi_post_work(struct work_struct *work)
166 {
167         
168         struct rk_fb_inf *inf = container_of(to_delayed_work(work), struct rk_fb_inf, delay_work);
169         struct rk_lcdc_device_driver * dev_drv = inf->lcdc_dev_drv[1];
170         dev_drv->pan_display(dev_drv,1);
171         
172 }
173
174 static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
175 {
176         struct rk_fb_inf *inf = dev_get_drvdata(info->device);
177         struct fb_fix_screeninfo *fix = &info->fix;
178         struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
179         struct fb_info * info2 = NULL; 
180         struct rk_lcdc_device_driver * dev_drv1  = NULL; 
181         struct layer_par *par = NULL;
182         struct layer_par *par2 = NULL;
183         int layer_id = 0;
184         u32 xoffset = var->xoffset;             // offset from virtual to visible 
185         u32 yoffset = var->yoffset;                             
186         u32 xvir = var->xres_virtual;
187         u8 data_format = var->nonstd&0xff;
188         CHK_SUSPEND(dev_drv);
189         layer_id = get_fb_layer_id(fix);
190         if(layer_id < 0)
191         {
192                 return  -ENODEV;
193         }
194         else
195         {
196                  par = dev_drv->layer_par[layer_id];
197         }
198         switch (par->format)
199         {
200                 case ARGB888:
201                         par->y_offset = (yoffset*xvir + xoffset)*4;
202                         break;
203                 case  RGB888:
204                         par->y_offset = (yoffset*xvir + xoffset)*3;
205                         break;
206                 case RGB565:
207                         par->y_offset = (yoffset*xvir + xoffset)*2;
208                         break;
209                 case  YUV422:
210                         par->y_offset = yoffset*xvir + xoffset;
211                         par->c_offset = par->y_offset;
212                         break;
213                 case  YUV420:
214                         par->y_offset = yoffset*xvir + xoffset;
215                         par->c_offset = (yoffset>>1)*xvir + xoffset;
216                         break;
217                 case  YUV444 : // yuv444
218                         par->y_offset = yoffset*xvir + xoffset;
219                         par->c_offset = yoffset*2*xvir +(xoffset<<1);
220                         break;
221                 default:
222                         printk("un supported format:0x%x\n",data_format);
223                         return -EINVAL;
224         }
225
226         #if defined(CONFIG_HDMI_RK30)
227                 #if defined(CONFIG_DUAL_DISP_IN_KERNEL)
228                         if(hdmi_get_hotplug())
229                         {
230                                 if(inf->num_fb >= 2)
231                                 {
232                                         info2 = inf->fb[2];
233                                         dev_drv1 = (struct rk_lcdc_device_driver * )info2->par;
234                                         par2 = dev_drv1->layer_par[layer_id];
235                                         par2->y_offset = par->y_offset;
236                                         //memcpy(info2->screen_base+par2->y_offset,info->screen_base+par->y_offset,
237                                         //      var->xres*var->yres*var->bits_per_pixel>>3);
238                                         fb_copy_by_ipp(info2,info,par->y_offset);
239                                         dev_drv1->pan_display(dev_drv1,layer_id);
240                                         //queue_delayed_work(inf->workqueue, &inf->delay_work,0);
241                                 }
242                         }
243                 #endif
244         #endif
245         dev_drv->pan_display(dev_drv,layer_id);
246         return 0;
247 }
248 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg)
249 {
250         struct rk_fb_inf *inf = dev_get_drvdata(info->device);
251         struct fb_fix_screeninfo *fix = &info->fix;
252         struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
253         u32 yuv_phy[2];
254         void __user *argp = (void __user *)arg;
255         fbprintk(">>>>>> %s : cmd:0x%x \n",__FUNCTION__,cmd);
256         
257         CHK_SUSPEND(dev_drv);
258         switch(cmd)
259         {
260                 case FBIOPUT_FBPHYADD:
261                         return info->fix.smem_start;
262                 case FB1_IOCTL_SET_YUV_ADDR:   //when in video mode, buff alloc by android
263                         if((!strcmp(fix->id,"fb1"))||(!strcmp(fix->id,"fb3")))
264                         {
265                                 if (copy_from_user(yuv_phy, argp, 8))
266                                         return -EFAULT;
267                                 info->fix.smem_start = yuv_phy[0];  //four y
268                                 info->fix.mmio_start = yuv_phy[1];  //four uv
269                         }
270                         break;
271                 case FBIOGET_OVERLAY_STATE:
272                         return inf->video_mode;
273                 case FBIOGET_SCREEN_STATE:
274                 case FBIOPUT_SET_CURSOR_EN:
275                 case FBIOPUT_SET_CURSOR_POS:
276                 case FBIOPUT_SET_CURSOR_IMG:
277                 case FBIOPUT_SET_CURSOR_CMAP:
278                 case FBIOPUT_GET_CURSOR_RESOLUTION:
279                 case FBIOPUT_GET_CURSOR_EN:
280                 case FB0_IOCTL_STOP_TIMER_FLUSH:    //stop timer flush mcu panel after android is runing
281                 case FBIOPUT_16OR32:
282                 case FBIOGET_16OR32:
283                 case FBIOGET_IDLEFBUff_16OR32:
284                 case FBIOSET_COMPOSE_LAYER_COUNTS:
285                 case FBIOGET_COMPOSE_LAYER_COUNTS:
286                 default:
287                         dev_drv->ioctl(dev_drv,cmd,arg,0);
288             break;
289     }
290     return 0;
291 }
292
293 static int rk_fb_blank(int blank_mode, struct fb_info *info)
294 {
295         struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
296         struct fb_fix_screeninfo *fix = &info->fix;
297         int layer_id;
298         CHK_SUSPEND(dev_drv);
299         layer_id = get_fb_layer_id(fix);
300         if(layer_id < 0)
301         {
302                 return  -ENODEV;
303         }
304         
305         dev_drv->blank(dev_drv,layer_id,blank_mode);
306
307         return 0;
308 }
309
310 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
311 {
312         struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
313         CHK_SUSPEND(dev_drv);
314         if( 0==var->xres_virtual || 0==var->yres_virtual ||
315                  0==var->xres || 0==var->yres || var->xres<16 ||
316                  ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) )
317          {
318                  printk(">>>>>> fb_check_var fail 1!!! \n");
319                  printk(">>>>>> 0==%d || 0==%d ", var->xres_virtual,var->yres_virtual);
320                  printk("0==%d || 0==%d || %d<16 || ", var->xres,var->yres,var->xres<16);
321                  printk("bits_per_pixel=%d \n", var->bits_per_pixel);
322                  return -EINVAL;
323          }
324  
325          if( (var->xoffset+var->xres)>var->xres_virtual ||
326                  (var->yoffset+var->yres)>var->yres_virtual*2 )
327          {
328                  printk(">>>>>> fb_check_var fail 2!!! \n");
329                  printk(">>>>>> (%d+%d)>%d || ", var->xoffset,var->xres,var->xres_virtual);
330                  printk("(%d+%d)>%d || ", var->yoffset,var->yres,var->yres_virtual);
331                  return -EINVAL;
332          }
333
334  
335     switch(var->nonstd&0x0f)
336     {
337         case 0: // rgb
338             switch(var->bits_per_pixel)
339             {
340             case 16:    // rgb565
341                 var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1);
342                 var->xres = (var->xres + 0x1) & (~0x1);
343                 var->xoffset = (var->xoffset) & (~0x1);
344                 break;
345             default:    // rgb888
346                 var->bits_per_pixel = 32;
347                 break;
348             }
349             var->nonstd &= ~0xc0;  //not support I2P in this format
350             break;
351         case 1: // yuv422
352             var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
353             var->xres = (var->xres + 0x3) & (~0x3);
354             var->xoffset = (var->xoffset) & (~0x3);
355             break;
356         case 2: // yuv4200
357             var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
358             var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1);
359             var->xres = (var->xres + 0x3) & (~0x3);
360             var->yres = (var->yres + 0x1) & (~0x1);
361             var->xoffset = (var->xoffset) & (~0x3);
362             var->yoffset = (var->yoffset) & (~0x1);
363             break;
364         case 3: // yuv4201
365             var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
366             var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1);
367             var->xres = (var->xres + 0x3) & (~0x3);
368             var->yres = (var->yres + 0x1) & (~0x1);
369             var->xoffset = (var->xoffset) & (~0x3);
370             var->yoffset = (var->yoffset) & (~0x1);
371             var->nonstd &= ~0xc0;   //not support I2P in this format
372             break;
373         case 4: // none
374         case 5: // yuv444
375             var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
376             var->xres = (var->xres + 0x3) & (~0x3);
377             var->xoffset = (var->xoffset) & (~0x3);
378             var->nonstd &= ~0xc0;   //not support I2P in this format
379             break;
380         default:
381             printk(">>>>>> fb1 var->nonstd=%d is invalid! \n", var->nonstd);
382             return -EINVAL;
383         }
384          
385     return 0;
386 }
387
388
389 static int rk_fb_set_par(struct fb_info *info)
390 {
391         struct rk_fb_inf *inf = dev_get_drvdata(info->device);
392         struct fb_var_screeninfo *var = &info->var;
393         struct fb_fix_screeninfo *fix = &info->fix;
394         struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
395         struct layer_par *par = NULL;
396         rk_screen *screen =dev_drv->screen;
397         struct fb_info * info2 = NULL;
398         struct rk_lcdc_device_driver * dev_drv1  = NULL;
399         struct layer_par *par2 = NULL;
400         int layer_id = 0;       
401         u32 cblen = 0,crlen = 0;
402         u16 xsize =0,ysize = 0;              //winx display window height/width --->LCDC_WINx_DSP_INFO
403         u32 xoffset = var->xoffset;             // offset from virtual to visible 
404         u32 yoffset = var->yoffset;             //resolution                    
405         u16 xpos = (var->nonstd>>8) & 0xfff; //visiable pos in panel
406         u16 ypos = (var->nonstd>>20) & 0xfff;
407         u32 xvir = var->xres_virtual;
408         u32 yvir = var->yres_virtual;
409         u8 data_format = var->nonstd&0xff;
410         var->pixclock = dev_drv->pixclock;
411         CHK_SUSPEND(dev_drv);
412         #if defined(CONFIG_HDMI_RK30)
413                 #if defined(CONFIG_DUAL_DISP_IN_KERNEL)
414                         if(hdmi_get_hotplug())
415                         {
416                                 if(inf->num_fb >= 2)
417                                 {
418                                         info2 = inf->fb[2];
419                                         dev_drv1 = (struct rk_lcdc_device_driver * )info2->par;
420                                 }
421                         }
422                 #endif 
423         #endif
424         layer_id = get_fb_layer_id(fix);
425         if(layer_id < 0)
426         {
427                 return  -ENODEV;
428         }
429         else
430         {
431                 par = dev_drv->layer_par[layer_id];
432                 if(dev_drv1)
433                 {
434                         par2 = dev_drv1->layer_par[layer_id];
435                 }
436         }
437         if((!strcmp(fix->id,"fb0"))||(!strcmp(fix->id,"fb2")))  //four ui
438         {
439                 xsize = screen->x_res;
440                 ysize = screen->y_res;
441         }
442         else if((!strcmp(fix->id,"fb1"))||(!strcmp(fix->id,"fb3")))
443         {
444                 xsize = (var->grayscale>>8) & 0xfff;  //visiable size in panel ,for vide0
445                 ysize = (var->grayscale>>20) & 0xfff;
446         }
447
448         /* calculate y_offset,c_offset,line_length,cblen and crlen  */
449 #if 1
450         switch (data_format)
451         {
452                 case HAL_PIXEL_FORMAT_RGBA_8888 :      // rgb
453                 case HAL_PIXEL_FORMAT_RGBX_8888: 
454                         par->format = ARGB888;
455                         fix->line_length = 4 * xvir;
456                         par->y_offset = (yoffset*xvir + xoffset)*4;
457                         break;
458                 case HAL_PIXEL_FORMAT_RGB_888 :
459                         par->format = RGB888;
460                         fix->line_length = 3 * xvir;
461                         par->y_offset = (yoffset*xvir + xoffset)*3;
462                         break;
463                 case HAL_PIXEL_FORMAT_RGB_565:  //RGB565
464                         par->format = RGB565;
465                         fix->line_length = 2 * xvir;
466                         par->y_offset = (yoffset*xvir + xoffset)*2;
467                         break;
468                 case HAL_PIXEL_FORMAT_YCbCr_422_SP : // yuv422
469                         par->format = YUV422;
470                         fix->line_length = xvir;
471                         cblen = crlen = (xvir*yvir)>>1;
472                         par->y_offset = yoffset*xvir + xoffset;
473                         par->c_offset = par->y_offset;
474                         break;
475                 case HAL_PIXEL_FORMAT_YCrCb_NV12   : // YUV420---uvuvuv
476                         par->format = YUV420;
477                         fix->line_length = xvir;
478                         cblen = crlen = (xvir*yvir)>>2;
479                         par->y_offset = yoffset*xvir + xoffset;
480                         par->c_offset = (yoffset>>1)*xvir + xoffset;
481                         break;
482                 case HAL_PIXEL_FORMAT_YCrCb_444 : // yuv444
483                         par->format = 5;
484                         fix->line_length = xvir<<2;
485                         par->y_offset = yoffset*xvir + xoffset;
486                         par->c_offset = yoffset*2*xvir +(xoffset<<1);
487                         cblen = crlen = (xvir*yvir);
488                         break;
489                 default:
490                         printk("un supported format:0x%x\n",data_format);
491                     return -EINVAL;
492         }
493 #else
494         switch(var->bits_per_pixel)
495         {
496                 case 32:
497                         par->format = ARGB888;
498                         fix->line_length = 4 * xvir;
499                         par->y_offset = (yoffset*xvir + xoffset)*4;
500                         break;
501                 case 16:
502                         par->format = RGB565;
503                         fix->line_length = 2 * xvir;
504                         par->y_offset = (yoffset*xvir + xoffset)*2;
505                         break;
506                         
507         }
508 #endif
509
510         par->xpos = xpos;
511         par->ypos = ypos;
512         par->xsize = xsize;
513         par->ysize = ysize;
514
515         par->smem_start =fix->smem_start;
516         par->cbr_start = fix->mmio_start;
517         par->xact = var->xres;              //winx active window height,is a part of vir
518         par->yact = var->yres;
519         par->xvir =  var->xres_virtual;         // virtual resolution    stride --->LCDC_WINx_VIR
520         par->yvir =  var->yres_virtual;
521
522         #if defined(CONFIG_HDMI_RK30)
523                 #if defined(CONFIG_DUAL_DISP_IN_KERNEL)
524                         if(hdmi_get_hotplug())
525                         {
526                                 par2->xact = par->xact;
527                                 par2->yact = par->yact;
528                                 par2->format = par->format;
529                                 dev_drv1->set_par(dev_drv1,layer_id);
530                         }
531                 #endif
532         #endif
533         dev_drv->set_par(dev_drv,layer_id);
534
535     
536         return 0;
537 }
538
539 static inline unsigned int chan_to_field(unsigned int chan,
540                                          struct fb_bitfield *bf)
541 {
542         chan &= 0xffff;
543         chan >>= 16 - bf->length;
544         return chan << bf->offset;
545 }
546
547 static int fb_setcolreg(unsigned regno,
548                                unsigned red, unsigned green, unsigned blue,
549                                unsigned transp, struct fb_info *info)
550 {
551         unsigned int val;
552
553         switch (info->fix.visual) {
554         case FB_VISUAL_TRUECOLOR:
555                 /* true-colour, use pseudo-palette */
556                 if (regno < 16) {
557                         u32 *pal = info->pseudo_palette;
558                         val  = chan_to_field(red,   &info->var.red);
559                         val |= chan_to_field(green, &info->var.green);
560                         val |= chan_to_field(blue,  &info->var.blue);
561                         pal[regno] = val;
562                 }
563                 break;
564         default:
565                 return -1;      /* unknown type */
566         }
567
568         return 0;
569 }
570
571 static struct fb_ops fb_ops = {
572     .owner          = THIS_MODULE,
573     .fb_open        = rk_fb_open,
574     .fb_release     = rk_fb_close,
575     .fb_check_var   = rk_fb_check_var,
576     .fb_set_par     = rk_fb_set_par,
577     .fb_blank       = rk_fb_blank,
578     .fb_ioctl       = rk_fb_ioctl,
579     .fb_pan_display = rk_pan_display,
580     .fb_setcolreg   = fb_setcolreg,
581     .fb_fillrect    = cfb_fillrect,
582     .fb_copyarea    = cfb_copyarea,
583     .fb_imageblit   = cfb_imageblit,
584 };
585
586
587
588 static struct fb_var_screeninfo def_var = {
589     .red    = {11,5,0},//default set to rgb565,the boot logo is rgb565
590     .green  = {5,6,0},
591     .blue   = {0,5,0},
592     .transp = {0,0,0},  
593     .nonstd      = HAL_PIXEL_FORMAT_RGB_565,   //(ypos<<20+xpos<<8+format) format
594     .grayscale   = 0,  //(ysize<<20+xsize<<8)
595     .activate    = FB_ACTIVATE_NOW,
596     .accel_flags = 0,
597     .vmode       = FB_VMODE_NONINTERLACED,
598 };
599
600 static struct fb_fix_screeninfo def_fix = {
601         .type            = FB_TYPE_PACKED_PIXELS,
602         .type_aux        = 0,
603         .xpanstep        = 1,
604         .ypanstep        = 1,
605         .ywrapstep       = 0,
606         .accel           = FB_ACCEL_NONE,
607         .visual          = FB_VISUAL_TRUECOLOR,
608                 
609 };
610
611
612 /*****************************************************************
613 this two function is for other module that in the kernel which
614 need show image directly through fb
615 fb_id:we have 4 fb here,default we use fb0 for ui display
616 *******************************************************************/
617 struct fb_info * rk_get_fb(int fb_id)
618 {
619     struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
620     struct fb_info *fb = inf->fb[fb_id];
621     return fb;
622 }
623 EXPORT_SYMBOL(rk_get_fb);
624
625 void rk_direct_fb_show(struct fb_info * fbi)
626 {
627     rk_fb_set_par(fbi);
628     rk_pan_display(&fbi->var, fbi);
629 }
630 EXPORT_SYMBOL(rk_direct_fb_show);
631
632
633 void rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id)
634 {
635         struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
636         struct fb_info *info = NULL;
637         struct fb_info *pmy_info = NULL;
638         struct rk_lcdc_device_driver * dev_drv = NULL;
639         struct fb_var_screeninfo *pmy_var = NULL;      //var for primary screen
640         struct fb_var_screeninfo *hdmi_var    = NULL;
641         struct fb_fix_screeninfo *pmy_fix = NULL;
642         struct fb_fix_screeninfo *hdmi_fix    = NULL;
643         int ret;
644         if(lcdc_id == 0)
645         {
646                 info = inf->fb[0];
647         }
648         else
649         {
650                 info = inf->fb[2] ;
651         }
652         
653         hdmi_var = &info->var;
654         hdmi_fix = &info->fix;
655         #if defined(CONFIG_DUAL_DISP_IN_KERNEL)
656                 pmy_var = &inf->fb[0]->var;
657                 pmy_fix = &inf->fb[0]->fix;
658                 hdmi_var->xres = pmy_var->xres;
659                 hdmi_var->yres = pmy_var->yres;
660                 hdmi_var->xres_virtual = pmy_var->xres_virtual;
661                 hdmi_var->yres_virtual = pmy_var->yres_virtual;
662                 hdmi_var->nonstd = pmy_var->nonstd;
663         #endif
664         //hdmi_fix->smem_start = pmy_fix->smem_start;
665         dev_drv = (struct rk_lcdc_device_driver * )info->par;
666         ret = dev_drv->load_screen(dev_drv,1);
667         ret = info->fbops->fb_open(info,1);
668         ret = info->fbops->fb_set_par(info);
669         #if defined(CONFIG_DUAL_DISP_IN_KERNEL)
670                 pmy_info = inf->fb[0];
671                 pmy_info->fbops->fb_pan_display(pmy_var,pmy_info);
672         #endif 
673
674 }
675 static int rk_request_fb_buffer(struct fb_info *fbi,int fb_id)
676 {
677         struct resource *res;
678         struct resource *mem;
679         int ret = 0;
680         switch(fb_id)
681         {
682                 case 0:
683                         res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb0 buf");
684                         if (res == NULL)
685                         {
686                                 dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
687                                 ret = -ENOENT;
688                         }
689                         fbi->fix.smem_start = res->start;
690                         fbi->fix.smem_len = res->end - res->start + 1;
691                         mem = request_mem_region(res->start, resource_size(res), g_fb_pdev->name);
692                         fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
693                         memset(fbi->screen_base, 0, fbi->fix.smem_len);
694                         printk("fb%d:phy:%lx>>vir:%p>>len:0x%x\n",fb_id,
695                                 fbi->fix.smem_start,fbi->screen_base,fbi->fix.smem_len);
696                 #ifdef CONFIG_FB_WORK_IPP // alloc ipp buf for rotate
697                         res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "ipp buf");
698                         if (res == NULL)
699                         {
700                                 dev_err(&g_fb_pdev->dev, "failed to get win1 ipp memory \n");
701                                 ret = -ENOENT;
702                         }
703                         fbi->fix.mmio_start = res->start;
704                         fbi->fix.mmio_len = res->end - res->start + 1;
705                 #endif
706                         break;
707                 case 2:
708                         res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb2 buf");
709                         if (res == NULL)
710                         {
711                         dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
712                         ret = -ENOENT;
713                         }
714                         fbi->fix.smem_start = res->start;
715                         fbi->fix.smem_len = res->end - res->start + 1;
716                         mem = request_mem_region(res->start, resource_size(res), g_fb_pdev->name);
717                         fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
718                         memset(fbi->screen_base, 0, fbi->fix.smem_len);
719                         printk("fb%d:phy:%lx>>vir:%p>>len:0x%x\n",fb_id,
720                                 fbi->fix.smem_start,fbi->screen_base,fbi->fix.smem_len);
721                         break;
722                 default:
723                         ret = -EINVAL;
724                         break;          
725         }
726     return ret;
727 }
728
729 static int rk_release_fb_buffer(struct fb_info *fbi)
730 {
731         if(!fbi)
732         {
733                 printk("no need release null fb buffer!\n");
734                 return -EINVAL;
735         }
736         if(!strcmp(fbi->fix.id,"fb1")||!strcmp(fbi->fix.id,"fb3"))  //buffer for fb1 and fb3 are alloc by android
737                 return 0;
738         iounmap(fbi->screen_base);
739         release_mem_region(fbi->fix.smem_start,fbi->fix.smem_len);
740         return 0;
741         
742 }
743 static int init_layer_par(struct rk_lcdc_device_driver *dev_drv)
744 {
745        int i;
746        struct layer_par * def_par = NULL;
747        int num_par = dev_drv->num_layer;
748        for(i = 0; i < num_par; i++)
749        {
750                struct layer_par *par = NULL;
751                par =  kzalloc(sizeof(struct layer_par), GFP_KERNEL);
752                if(!par)
753                {
754                        printk(KERN_ERR "kzmalloc for layer_par fail!");
755                        return   -ENOMEM;
756                        
757                }
758                def_par = &dev_drv->def_layer_par[i];
759                strcpy(par->name,def_par->name);
760                par->id = def_par->id;
761                par->support_3d = def_par->support_3d;
762                dev_drv->layer_par[i] = par;
763        }
764                
765        return 0;
766        
767        
768 }
769
770
771 static int init_lcdc_device_driver(struct rk_lcdc_device_driver *dev_drv,
772         struct rk_lcdc_device_driver *def_drv,int id)
773 {
774         if(!def_drv)
775         {
776                 printk(KERN_ERR "default lcdc device driver is null!\n");
777                 return -EINVAL;
778         }
779         if(!dev_drv)
780         {
781                 printk(KERN_ERR "lcdc device driver is null!\n");
782                 return -EINVAL; 
783         }
784         sprintf(dev_drv->name, "lcdc%d",id);
785         dev_drv->id             = id;
786         dev_drv->open           = def_drv->open;
787         dev_drv->init_lcdc      = def_drv->init_lcdc;
788         dev_drv->ioctl          = def_drv->ioctl;
789         dev_drv->blank          = def_drv->blank;
790         dev_drv->set_par        = def_drv->set_par;
791         dev_drv->pan_display    = def_drv->pan_display;
792         dev_drv->suspend        = def_drv->suspend;
793         dev_drv->resume         = def_drv->resume;
794         dev_drv->load_screen    = def_drv->load_screen;
795         dev_drv->def_layer_par  = def_drv->def_layer_par;
796         dev_drv->num_layer      = def_drv->num_layer;
797         dev_drv->get_layer_state= def_drv->get_layer_state;
798         dev_drv->get_disp_info  = def_drv->get_disp_info;
799         init_layer_par(dev_drv);
800         init_completion(&dev_drv->frame_done);
801         spin_lock_init(&dev_drv->cpl_lock);
802         dev_drv->first_frame = 1;
803         
804         return 0;
805 }
806
807 int rk_fb_register(struct rk_lcdc_device_driver *dev_drv,
808         struct rk_lcdc_device_driver *def_drv,int id)
809 {
810         struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
811         struct fb_info *fbi;
812         int i=0,ret = 0;
813         int lcdc_id = 0;
814         if(NULL == dev_drv)
815         {
816                 printk("null lcdc device driver?");
817                 return -ENOENT;
818         }
819         for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++)
820         {
821                 if(NULL==fb_inf->lcdc_dev_drv[i])
822                 {
823                         fb_inf->lcdc_dev_drv[i] = dev_drv;
824                         fb_inf->lcdc_dev_drv[i]->id = i;
825                         fb_inf->num_lcdc++;
826                         break;
827                 }
828         }
829         if(i==RK30_MAX_LCDC_SUPPORT)
830         {
831                 printk("rk_fb_register lcdc out of support %d",i);
832                 return -ENOENT;
833         }
834         lcdc_id = i;
835         init_lcdc_device_driver(dev_drv, def_drv,id);
836         if(dev_drv->screen_ctr_info->set_screen_info)
837         {
838                 dev_drv->screen_ctr_info->set_screen_info(dev_drv->screen,
839                         dev_drv->screen_ctr_info->lcd_info);
840                 if(dev_drv->screen_ctr_info->io_init)
841                         dev_drv->screen_ctr_info->io_init(NULL);
842         }
843         else
844         {
845                 printk(KERN_WARNING "no display device on lcdc%d!?\n",dev_drv->id);
846                 return -ENODEV;
847         }
848                 
849         dev_drv->init_lcdc(dev_drv);
850         dev_drv->load_screen(dev_drv,1);
851         /************fb set,one layer one fb ***********/
852         dev_drv->fb_index_base = fb_inf->num_fb;
853     for(i=0;i<dev_drv->num_layer;i++)
854     {
855         fbi= framebuffer_alloc(0, &g_fb_pdev->dev);
856         if(!fbi)
857         {
858             dev_err(&g_fb_pdev->dev,">> fb framebuffer_alloc fail!");
859             fbi = NULL;
860             ret = -ENOMEM;
861         }
862         fbi->par = dev_drv;
863         fbi->var = def_var;
864         fbi->fix = def_fix;
865         sprintf(fbi->fix.id,"fb%d",fb_inf->num_fb);
866         fbi->var.xres = fb_inf->lcdc_dev_drv[lcdc_id]->screen->x_res;
867         fbi->var.yres = fb_inf->lcdc_dev_drv[lcdc_id]->screen->y_res;
868         fbi->var.bits_per_pixel = 16;
869         fbi->var.xres_virtual = fb_inf->lcdc_dev_drv[lcdc_id]->screen->x_res;
870         fbi->var.yres_virtual = fb_inf->lcdc_dev_drv[lcdc_id]->screen->y_res;
871         fbi->var.width = fb_inf->lcdc_dev_drv[lcdc_id]->screen->width;
872         fbi->var.height = fb_inf->lcdc_dev_drv[lcdc_id]->screen->height;
873         fbi->var.pixclock = fb_inf->lcdc_dev_drv[lcdc_id]->pixclock;
874         fbi->var.left_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen->left_margin;
875         fbi->var.right_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen->right_margin;
876         fbi->var.upper_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen->upper_margin;
877         fbi->var.lower_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen->lower_margin;
878         fbi->var.vsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->screen->vsync_len;
879         fbi->var.hsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->screen->hsync_len;
880         fbi->fbops                       = &fb_ops;
881         fbi->flags                       = FBINFO_FLAG_DEFAULT;
882         fbi->pseudo_palette  = fb_inf->lcdc_dev_drv[lcdc_id]->layer_par[i]->pseudo_pal;
883         rk_request_fb_buffer(fbi,fb_inf->num_fb);
884         ret = register_framebuffer(fbi);
885         if(ret<0)
886         {
887             printk("%s>>fb%d register_framebuffer fail!\n",__func__,fb_inf->num_fb);
888             ret = -EINVAL;
889         }
890         rkfb_create_sysfs(fbi);
891         fb_inf->fb[fb_inf->num_fb] = fbi;
892         printk("%s>>>>>%s\n",__func__,fb_inf->fb[fb_inf->num_fb]->fix.id);
893         fb_inf->num_fb++;       
894         }
895 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
896
897     if(id == 0)
898     {
899             fb_inf->fb[fb_inf->num_fb-2]->fbops->fb_open(fb_inf->fb[fb_inf->num_fb-2],1);
900             fb_inf->fb[fb_inf->num_fb-2]->fbops->fb_set_par(fb_inf->fb[fb_inf->num_fb-2]);
901             if(fb_prepare_logo(fb_inf->fb[fb_inf->num_fb-2], FB_ROTATE_UR)) {
902                 /* Start display and show logo on boot */
903                 fb_set_cmap(&fb_inf->fb[fb_inf->num_fb-2]->cmap, fb_inf->fb[fb_inf->num_fb-2]);
904                 fb_show_logo(fb_inf->fb[fb_inf->num_fb-2], FB_ROTATE_UR);
905                 fb_inf->fb[fb_inf->num_fb-2]->fbops->fb_pan_display(&(fb_inf->fb[fb_inf->num_fb-2]->var), fb_inf->fb[fb_inf->num_fb-2]);
906             }
907     }
908 #endif
909         return 0;
910         
911         
912 }
913 int rk_fb_unregister(struct rk_lcdc_device_driver *dev_drv)
914 {
915
916         struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
917         struct fb_info *fbi;
918         int fb_index_base = dev_drv->fb_index_base;
919         int fb_num = dev_drv->num_layer;
920         int i=0;
921         if(NULL == dev_drv)
922         {
923                 printk(" no need to unregister null lcdc device driver!\n");
924                 return -ENOENT;
925         }
926
927         for(i = 0; i < fb_num; i++)
928         {
929                 kfree(dev_drv->layer_par[i]);
930         }
931
932         for(i=fb_index_base;i<(fb_index_base+fb_num);i++)
933         {
934                 fbi = fb_inf->fb[i];
935                 unregister_framebuffer(fbi);
936                 rk_release_fb_buffer(fbi);
937                 framebuffer_release(fbi);       
938         }
939         fb_inf->lcdc_dev_drv[dev_drv->id]= NULL;
940
941         return 0;
942 }
943
944
945
946 #ifdef CONFIG_HAS_EARLYSUSPEND
947 struct suspend_info {
948         struct early_suspend early_suspend;
949         struct rk_fb_inf *inf;
950 };
951
952 static void rkfb_early_suspend(struct early_suspend *h)
953 {
954         struct suspend_info *info = container_of(h, struct suspend_info,
955                                                 early_suspend);
956         struct rk_fb_inf *inf = info->inf;
957         int i;
958         for(i = 0; i < inf->num_lcdc; i++)
959         {
960                 atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,1);
961                 if(inf->lcdc_dev_drv[i]->screen_ctr_info->io_disable)
962                         inf->lcdc_dev_drv[i]->screen_ctr_info->io_disable();
963                 if(inf->lcdc_dev_drv[i]->screen->standby)
964                         inf->lcdc_dev_drv[i]->screen->standby(1);
965                 
966                 inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
967         }
968 }
969 static void rkfb_early_resume(struct early_suspend *h)
970 {
971         struct suspend_info *info = container_of(h, struct suspend_info,
972                                                 early_suspend);
973         struct rk_fb_inf *inf = info->inf;
974         int i;
975         for(i = 0; i < inf->num_lcdc; i++)
976         {
977                 if(inf->lcdc_dev_drv[i]->screen_ctr_info->io_enable)
978                         inf->lcdc_dev_drv[i]->screen_ctr_info->io_enable();
979                 if(inf->lcdc_dev_drv[i]->screen->standby)
980                         inf->lcdc_dev_drv[i]->screen->standby(0);
981                 
982                 inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]);
983                 atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,0);
984         }
985
986 }
987
988
989
990 static struct suspend_info suspend_info = {
991         .early_suspend.suspend = rkfb_early_suspend,
992         .early_suspend.resume = rkfb_early_resume,
993         .early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
994 };
995 #endif
996
997 static int __devinit rk_fb_probe (struct platform_device *pdev)
998 {
999         struct rk_fb_inf *fb_inf = NULL;
1000         struct rk29fb_info * mach_info = NULL;
1001         int ret = 0;
1002         g_fb_pdev=pdev;
1003         /* Malloc rk_fb_inf and set it to pdev for drvdata */
1004         fb_inf = kzalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
1005         if(!fb_inf)
1006         {
1007                 dev_err(&pdev->dev, ">>fb inf kmalloc fail!");
1008                 ret = -ENOMEM;
1009         }
1010         platform_set_drvdata(pdev,fb_inf);
1011 #if defined(CONFIG_HDMI_RK30)
1012                 #if defined(CONFIG_DUAL_DISP_IN_KERNEL)         
1013                         fb_inf->workqueue = create_singlethread_workqueue("hdmi_post");
1014                         INIT_DELAYED_WORK(&(fb_inf->delay_work), hdmi_post_work);
1015                 #endif
1016 #endif
1017
1018 #ifdef CONFIG_HAS_EARLYSUSPEND
1019         suspend_info.inf = fb_inf;
1020         register_early_suspend(&suspend_info.early_suspend);
1021 #endif
1022         printk("rk fb probe ok!\n");
1023     return 0;
1024 }
1025
1026 static int __devexit rk_fb_remove(struct platform_device *pdev)
1027 {
1028         struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
1029         kfree(fb_inf);
1030         platform_set_drvdata(pdev, NULL);
1031         return 0;
1032 }
1033
1034 static void rk_fb_shutdown(struct platform_device *pdev)
1035 {
1036         struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
1037         kfree(fb_inf);
1038         platform_set_drvdata(pdev, NULL);
1039 }
1040
1041 static struct platform_driver rk_fb_driver = {
1042         .probe          = rk_fb_probe,
1043         .remove         = __devexit_p(rk_fb_remove),
1044         .driver         = {
1045                 .name   = "rk-fb",
1046                 .owner  = THIS_MODULE,
1047         },
1048         //.shutdown   = rk_fb_shutdown,
1049 };
1050
1051 static int __init rk_fb_init(void)
1052 {
1053     return platform_driver_register(&rk_fb_driver);
1054 }
1055
1056 static void __exit rk_fb_exit(void)
1057 {
1058     platform_driver_unregister(&rk_fb_driver);
1059 }
1060
1061 subsys_initcall_sync(rk_fb_init);
1062 module_exit(rk_fb_exit);
1063