bmp Full resolution support for factoryTool 4.0
[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/kthread.h>
26 #include <linux/fb.h>
27 #include <linux/init.h>
28 #include <linux/platform_device.h>
29 #include <linux/earlysuspend.h>
30 #include <asm/div64.h>
31 #include <asm/uaccess.h>
32 #include<linux/rk_fb.h>
33 #include <plat/ipp.h>
34 #include "hdmi/rk_hdmi.h"
35 #include <linux/linux_logo.h>
36
37 void rk29_backlight_set(bool on);
38 bool rk29_get_backlight_status(void);
39
40 #ifdef  CONFIG_FB_MIRRORING
41
42
43 int (*video_data_to_mirroring)(struct fb_info *info,u32 yuv_phy[2]) = NULL;
44 EXPORT_SYMBOL(video_data_to_mirroring);
45
46 #endif
47 static struct platform_device *g_fb_pdev;
48
49 static struct rk_fb_rgb def_rgb_16 = {
50      red:    { offset: 11, length: 5, },
51      green:  { offset: 5,  length: 6, },
52      blue:   { offset: 0,  length: 5, },
53      transp: { offset: 0,  length: 0, },
54 };
55
56
57 /***************************************************************************
58 fb0-----------lcdc0------------win1  for ui
59 fb1-----------lcdc0------------win0  for video,win0 support 3d display
60 fb2-----------lcdc1------------win1  for ui
61 fb3-----------lcdc1-------------win0 for video ,win0 support 3d display
62
63 defautl:we alloc three buffer,one for fb0 and fb2 display ui,one for ipp rotate
64         fb1 and fb3 are used for video play,the buffer is alloc by android,and
65         pass the phy addr to fix.smem_start by ioctl
66 ****************************************************************************/
67
68
69
70 /**********************************************************************
71 this is for hdmi
72 name: lcdc device name ,lcdc0 , lcdc1
73 ***********************************************************************/
74 struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name)
75 {
76         struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
77         int i = 0;
78         for( i = 0; i < inf->num_lcdc; i++)
79         {
80                 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
81                         break;
82         }
83         return inf->lcdc_dev_drv[i];
84         
85 }
86 static int rk_fb_open(struct fb_info *info,int user)
87 {
88     struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
89     int layer_id;
90   
91     layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
92     if(dev_drv->layer_par[layer_id]->state)
93     {
94         return 0;    // if this layer aready opened ,no need to reopen
95     }
96     else
97     {
98         dev_drv->open(dev_drv,layer_id,1);
99     }
100     
101     return 0;
102     
103 }
104
105 static int rk_fb_close(struct fb_info *info,int user)
106 {
107         /*struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
108         int layer_id;
109         CHK_SUSPEND(dev_drv);
110         layer_id = get_fb_layer_id(&info->fix);
111         if(!dev_drv->layer_par[layer_id]->state)
112         {
113                 return 0;
114         }
115         else
116         {
117                 dev_drv->open(dev_drv,layer_id,0);
118         }*/
119         
120         return 0;
121 }
122 static void fb_copy_by_ipp(struct fb_info *dst_info, struct fb_info *src_info,int offset)
123 {
124         struct rk29_ipp_req ipp_req;
125
126         uint32_t  rotation = 0;
127 #if defined(CONFIG_FB_ROTATE)
128         int orientation = orientation = 270 - CONFIG_ROTATE_ORIENTATION;
129         switch(orientation)
130         {
131                 case 0:
132                         rotation = IPP_ROT_0;
133                         break;
134                 case 90:
135                         rotation = IPP_ROT_90;
136                         break;
137                 case 180:
138                         rotation = IPP_ROT_180;
139                         break;
140                 case 270:
141                         rotation = IPP_ROT_270;
142                         break;
143                 default:
144                         rotation = IPP_ROT_270;
145                         break;
146                         
147         }
148 #endif
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 = rotation;
162         ipp_blit_sync(&ipp_req);
163         
164 }
165
166
167 #if 0
168
169 static void hdmi_post_work(struct work_struct *work)
170 {       
171         struct rk_fb_inf *inf = container_of(to_delayed_work(work), struct rk_fb_inf, delay_work);
172         struct fb_info * info2 = inf->fb[2];    
173         struct fb_info * info = inf->fb[0];     
174         struct rk_lcdc_device_driver * dev_drv1  = (struct rk_lcdc_device_driver * )info2->par;
175         struct rk_lcdc_device_driver * dev_drv  = (struct rk_lcdc_device_driver * )info->par;
176         struct layer_par *par = dev_drv->layer_par[1];
177         struct layer_par *par2 = dev_drv1->layer_par[1];        
178         struct fb_var_screeninfo *var = &info->var;   
179         u32 xvir = var->xres_virtual;   
180         dev_drv1->xoffset = var->xoffset;             // offset from virtual to visible 
181         dev_drv1->yoffset += var->yres; 
182         if(dev_drv1->yoffset >= 3*var->yres)
183                 dev_drv1->yoffset = 0;++        
184                 rk_bufferoffset_tran(dev_drv1->xoffset, dev_drv1->yoffset, xvir , par2);
185         fb_copy_by_ipp(info2,info,par->y_offset,par2->y_offset);
186         dev_drv1->pan_display(dev_drv1,1);
187         complete(&(dev_drv1->ipp_done));
188 }
189 #endif
190
191 static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
192 {
193         struct rk_fb_inf *inf = dev_get_drvdata(info->device);
194         struct fb_fix_screeninfo *fix = &info->fix;
195         struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
196         struct fb_info * info2 = NULL; 
197         struct rk_lcdc_device_driver * dev_drv1  = NULL; 
198         struct layer_par *par = NULL;
199         struct layer_par *par2 = NULL;
200         int layer_id = 0;
201         u32 xoffset = var->xoffset;             // offset from virtual to visible 
202         u32 yoffset = var->yoffset;                             
203         u32 xvir = var->xres_virtual;
204         u8 data_format = var->nonstd&0xff;
205         
206         layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
207         if(layer_id < 0)
208         {
209                 return  -ENODEV;
210         }
211         else
212         {
213                  par = dev_drv->layer_par[layer_id];
214         }
215         switch (par->format)
216         {
217                 case XBGR888:
218                 case ARGB888:
219                 case ABGR888:
220                         par->y_offset = (yoffset*xvir + xoffset)*4;
221                         break;
222                 case  RGB888:
223                         par->y_offset = (yoffset*xvir + xoffset)*3;
224                         break;
225                 case RGB565:
226                         par->y_offset = (yoffset*xvir + xoffset)*2;
227                         break;
228                 case  YUV422:
229                         par->y_offset = yoffset*xvir + xoffset;
230                         par->c_offset = par->y_offset;
231                         break;
232                 case  YUV420:
233                         par->y_offset = yoffset*xvir + xoffset;
234                         par->c_offset = (yoffset>>1)*xvir + xoffset;
235                         break;
236                 case  YUV444 : // yuv444
237                         par->y_offset = yoffset*xvir + xoffset;
238                         par->c_offset = yoffset*2*xvir +(xoffset<<1);
239                         break;
240                 default:
241                         printk("un supported format:0x%x\n",data_format);
242                         return -EINVAL;
243         }
244
245         #if defined(CONFIG_RK_HDMI)
246                 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
247                         if(hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
248                         {
249                                 if(inf->num_fb >= 2)
250                                 {
251                                         info2 = inf->fb[inf->num_fb>>1];
252                                         dev_drv1 = (struct rk_lcdc_device_driver * )info2->par;
253                                         par2 = dev_drv1->layer_par[layer_id];
254                                         par2->y_offset = par->y_offset;
255                                         //memcpy(info2->screen_base+par2->y_offset,info->screen_base+par->y_offset,
256                                         //      var->xres*var->yres*var->bits_per_pixel>>3);
257                                         #if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
258                                         fb_copy_by_ipp(info2,info,par->y_offset);
259                                         #endif
260                                         dev_drv1->pan_display(dev_drv1,layer_id);
261                                         //queue_delayed_work(inf->workqueue, &inf->delay_work,0);
262                                 }
263                         }
264                 #endif
265         #endif
266         dev_drv->pan_display(dev_drv,layer_id);
267         #ifdef  CONFIG_FB_MIRRORING
268         if(video_data_to_mirroring!=NULL)
269                 video_data_to_mirroring(info,NULL);
270         #endif
271         return 0;
272 }
273 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg)
274 {
275         struct fb_fix_screeninfo *fix = &info->fix;
276         struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
277         u32 yuv_phy[2];
278         int  layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
279         int enable; // enable fb:1 enable;0 disable 
280         int ovl;        //overlay:0 win1 on the top of win0;1,win0 on the top of win1
281         int num_buf; //buffer_number
282         void __user *argp = (void __user *)arg;
283         
284         switch(cmd)
285         {
286                 case FBIOPUT_FBPHYADD:
287                         return info->fix.smem_start;
288                         break;
289                 case RK_FBIOSET_YUV_ADDR:   //when in video mode, buff alloc by android
290                         //if((!strcmp(fix->id,"fb1"))||(!strcmp(fix->id,"fb3")))
291                         {
292                                 if (copy_from_user(yuv_phy, argp, 8))
293                                         return -EFAULT;
294                                 info->fix.smem_start = yuv_phy[0];  //four y
295                                 info->fix.mmio_start = yuv_phy[1];  //four uv
296                         }
297                         break;
298                 case RK_FBIOSET_ENABLE:
299                         if (copy_from_user(&enable, argp, sizeof(enable)))
300                                 return -EFAULT;
301                         dev_drv->open(dev_drv,layer_id,enable);
302                         break;
303                 case RK_FBIOGET_ENABLE:
304                         enable = dev_drv->get_layer_state(dev_drv,layer_id);
305                         if(copy_to_user(argp,&enable,sizeof(enable)))
306                                 return -EFAULT;
307                         break;
308                 case RK_FBIOSET_OVERLAY_STATE:
309                         if (copy_from_user(&ovl, argp, sizeof(ovl)))
310                                 return -EFAULT;
311                         dev_drv->ovl_mgr(dev_drv,ovl,1);
312                         break;
313                 case RK_FBIOGET_OVERLAY_STATE:
314                         ovl = dev_drv->ovl_mgr(dev_drv,0,0);
315                         if (copy_to_user(argp, &ovl, sizeof(ovl)))
316                                 return -EFAULT;
317                         break;
318                 case RK_FBIOPUT_NUM_BUFFERS:
319                         if (copy_from_user(&num_buf, argp, sizeof(num_buf)))
320                                 return -EFAULT;
321                         dev_drv->num_buf = num_buf;
322                         printk("rk fb use %d buffers\n",num_buf);
323                         break;
324                 case RK_FBIOSET_VSYNC_ENABLE:
325                         if (copy_from_user(&enable, argp, sizeof(enable)))
326                                 return -EFAULT;
327                         dev_drv->vsync_info.active = enable;
328                         break;
329                 default:
330                         dev_drv->ioctl(dev_drv,cmd,arg,layer_id);
331                         break;
332     }
333     return 0;
334 }
335
336 static int rk_fb_blank(int blank_mode, struct fb_info *info)
337 {
338         struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
339         struct fb_fix_screeninfo *fix = &info->fix;
340         int layer_id;
341         
342         layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
343         if(layer_id < 0)
344         {
345                 return  -ENODEV;
346         }
347 #if defined(CONFIG_RK_HDMI)
348 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
349         if(hdmi_get_hotplug() == HDMI_HPD_ACTIVED){
350                 printk("hdmi is connect , not blank lcdc\n");
351         }else
352 #endif
353 #endif
354         {
355                 dev_drv->blank(dev_drv,layer_id,blank_mode);
356         }
357         return 0;
358 }
359
360 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
361 {
362         
363         if( 0==var->xres_virtual || 0==var->yres_virtual ||
364                  0==var->xres || 0==var->yres || var->xres<16 ||
365                  ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) )
366          {
367                  printk("%s check var fail 1!!! \n",info->fix.id);
368                  printk("xres_vir:%d>>yres_vir:%d\n", var->xres_virtual,var->yres_virtual);
369                  printk("xres:%d>>yres:%d\n", var->xres,var->yres);
370                  printk("bits_per_pixel:%d \n", var->bits_per_pixel);
371                  return -EINVAL;
372          }
373  
374          if( ((var->xoffset+var->xres) > var->xres_virtual) ||
375              ((var->yoffset+var->yres) > (var->yres_virtual)) )
376          {
377                  printk("%s check_var fail 2!!! \n",info->fix.id);
378                  printk("xoffset:%d>>xres:%d>>xres_vir:%d\n",var->xoffset,var->xres,var->xres_virtual);
379                  printk("yoffset:%d>>yres:%d>>yres_vir:%d\n",var->yoffset,var->yres,var->yres_virtual);
380                  return -EINVAL;
381          }
382
383     return 0;
384 }
385
386
387 static int rk_fb_set_par(struct fb_info *info)
388 {
389         struct rk_fb_inf *inf = dev_get_drvdata(info->device);
390         struct fb_var_screeninfo *var = &info->var;
391         struct fb_fix_screeninfo *fix = &info->fix;
392         struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
393         struct layer_par *par = NULL;
394         rk_screen *screen =dev_drv->cur_screen;
395         struct fb_info * info2 = NULL;
396         struct rk_lcdc_device_driver * dev_drv1  = NULL;
397         struct layer_par *par2 = NULL;
398         int layer_id = 0;       
399         u32 cblen = 0,crlen = 0;
400         u16 xsize =0,ysize = 0;              //winx display window height/width --->LCDC_WINx_DSP_INFO
401         u32 xoffset = var->xoffset;             // offset from virtual to visible 
402         u32 yoffset = var->yoffset;             //resolution                    
403         u16 xpos = (var->nonstd>>8) & 0xfff; //visiable pos in panel
404         u16 ypos = (var->nonstd>>20) & 0xfff;
405         u32 xvir = var->xres_virtual;
406         u32 yvir = var->yres_virtual;
407         u8 data_format = var->nonstd&0xff;
408         var->pixclock = dev_drv->pixclock;
409         
410         #if defined(CONFIG_RK_HDMI)
411                 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
412                         if(hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
413                         {
414                                 if(inf->num_fb >= 2)
415                                 {
416                                         info2 = inf->fb[inf->num_fb>>1];
417                                         dev_drv1 = (struct rk_lcdc_device_driver * )info2->par;
418                                 }
419                         }
420                 #endif 
421         #endif
422         layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
423         if(layer_id < 0)
424         {
425                 return  -ENODEV;
426         }
427         else
428         {
429                 par = dev_drv->layer_par[layer_id];
430                 if(dev_drv1)
431                 {
432                         par2 = dev_drv1->layer_par[layer_id];
433                 }
434         }
435         
436         if(var->grayscale>>8)  //if the application has specific the horizontal and vertical display size
437         {
438                 xsize = (var->grayscale>>8) & 0xfff;  //visiable size in panel ,for vide0
439                 ysize = (var->grayscale>>20) & 0xfff;
440         }
441         else  //ohterwise  full  screen display
442         {
443                 xsize = screen->x_res;
444                 ysize = screen->y_res;
445         }
446
447 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) || defined(CONFIG_NO_DUAL_DISP)
448         if(screen->screen_id == 0) //this is for device like rk2928 ,whic have one lcdc but two display outputs
449         {                          //save parameter set by android
450                 dev_drv->screen0->xsize = xsize;
451                 dev_drv->screen0->ysize = ysize;
452                 dev_drv->screen0->xpos  = xpos;
453                 dev_drv->screen0->ypos = ypos;
454         }
455         else
456         {
457                 xsize = dev_drv->screen1->xsize; 
458                 ysize = dev_drv->screen1->ysize;
459                 xpos = dev_drv->screen1->xpos;
460                 ypos = dev_drv->screen1->ypos;
461         }
462 #endif
463         /* calculate y_offset,c_offset,line_length,cblen and crlen  */
464 #if 1
465         switch (data_format)
466         {
467                 case HAL_PIXEL_FORMAT_RGBX_8888: 
468                         par->format = XBGR888;
469                         fix->line_length = 4 * xvir;
470                         par->y_offset = (yoffset*xvir + xoffset)*4;
471                         break;
472                 case HAL_PIXEL_FORMAT_RGBA_8888 :      // rgb
473                         par->format = ABGR888;
474                         fix->line_length = 4 * xvir;
475                         par->y_offset = (yoffset*xvir + xoffset)*4;
476                         break;
477                 case HAL_PIXEL_FORMAT_BGRA_8888 :      // rgb
478                         par->format = ARGB888;
479                         fix->line_length = 4 * xvir;
480                         par->y_offset = (yoffset*xvir + xoffset)*4;
481                         break;
482                 case HAL_PIXEL_FORMAT_RGB_888 :
483                         par->format = RGB888;
484                         fix->line_length = 3 * xvir;
485                         par->y_offset = (yoffset*xvir + xoffset)*3;
486                         break;
487                 case HAL_PIXEL_FORMAT_RGB_565:  //RGB565
488                         par->format = RGB565;
489                         fix->line_length = 2 * xvir;
490                         par->y_offset = (yoffset*xvir + xoffset)*2;
491                         break;
492                 case HAL_PIXEL_FORMAT_YCbCr_422_SP : // yuv422
493                         par->format = YUV422;
494                         fix->line_length = xvir;
495                         cblen = crlen = (xvir*yvir)>>1;
496                         par->y_offset = yoffset*xvir + xoffset;
497                         par->c_offset = par->y_offset;
498                         break;
499                 case HAL_PIXEL_FORMAT_YCrCb_NV12   : // YUV420---uvuvuv
500                         par->format = YUV420;
501                         fix->line_length = xvir;
502                         cblen = crlen = (xvir*yvir)>>2;
503                         par->y_offset = yoffset*xvir + xoffset;
504                         par->c_offset = (yoffset>>1)*xvir + xoffset;
505                         break;
506                 case HAL_PIXEL_FORMAT_YCrCb_444 : // yuv444
507                         par->format = 5;
508                         fix->line_length = xvir<<2;
509                         par->y_offset = yoffset*xvir + xoffset;
510                         par->c_offset = yoffset*2*xvir +(xoffset<<1);
511                         cblen = crlen = (xvir*yvir);
512                         break;
513                 default:
514                         printk("%s:un supported format:0x%x\n",__func__,data_format);
515                     return -EINVAL;
516         }
517 #else
518         switch(var->bits_per_pixel)
519         {
520                 case 32:
521                         par->format = ARGB888;
522                         fix->line_length = 4 * xvir;
523                         par->y_offset = (yoffset*xvir + xoffset)*4;
524                         break;
525                 case 16:
526                         par->format = RGB565;
527                         fix->line_length = 2 * xvir;
528                         par->y_offset = (yoffset*xvir + xoffset)*2;
529                         break;
530                         
531         }
532 #endif
533
534         par->xpos = xpos;
535         par->ypos = ypos;
536         par->xsize = xsize;
537         par->ysize = ysize;
538
539         par->smem_start =fix->smem_start;
540         par->cbr_start = fix->mmio_start;
541         par->xact = var->xres;              //winx active window height,is a part of vir
542         par->yact = var->yres;
543         par->xvir =  var->xres_virtual;         // virtual resolution    stride --->LCDC_WINx_VIR
544         par->yvir =  var->yres_virtual;
545
546         #if defined(CONFIG_RK_HDMI)
547                 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
548                         if(hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
549                         {
550                                 if(info != info2)
551                                 {
552                                         par2->xact = par->xact;
553                                         par2->yact = par->yact;
554                                         par2->format = par->format;
555                                         info2->var.nonstd &= 0xffffff00;
556                                         info2->var.nonstd |= data_format;
557                                         dev_drv1->set_par(dev_drv1,layer_id);
558                                 }
559                         }
560                 #endif
561         #endif
562         dev_drv->set_par(dev_drv,layer_id);
563
564     
565         return 0;
566 }
567
568 static inline unsigned int chan_to_field(unsigned int chan,
569                                          struct fb_bitfield *bf)
570 {
571         chan &= 0xffff;
572         chan >>= 16 - bf->length;
573         return chan << bf->offset;
574 }
575
576 static int fb_setcolreg(unsigned regno,
577                                unsigned red, unsigned green, unsigned blue,
578                                unsigned transp, struct fb_info *info)
579 {
580         unsigned int val;
581
582         switch (info->fix.visual) {
583         case FB_VISUAL_TRUECOLOR:
584                 /* true-colour, use pseudo-palette */
585                 if (regno < 16) {
586                         u32 *pal = info->pseudo_palette;
587                         val  = chan_to_field(red,   &info->var.red);
588                         val |= chan_to_field(green, &info->var.green);
589                         val |= chan_to_field(blue,  &info->var.blue);
590                         pal[regno] = val;
591                 }
592                 break;
593         default:
594                 return -1;      /* unknown type */
595         }
596
597         return 0;
598 }
599
600 static struct fb_ops fb_ops = {
601     .owner          = THIS_MODULE,
602     .fb_open        = rk_fb_open,
603     .fb_release     = rk_fb_close,
604     .fb_check_var   = rk_fb_check_var,
605     .fb_set_par     = rk_fb_set_par,
606     .fb_blank       = rk_fb_blank,
607     .fb_ioctl       = rk_fb_ioctl,
608     .fb_pan_display = rk_pan_display,
609     .fb_setcolreg   = fb_setcolreg,
610     .fb_fillrect    = cfb_fillrect,
611     .fb_copyarea    = cfb_copyarea,
612     .fb_imageblit   = cfb_imageblit,
613 };
614
615
616
617 static struct fb_var_screeninfo def_var = {
618         .red    = {11,5,0},//default set to rgb565,the boot logo is rgb565
619         .green  = {5,6,0},
620         .blue   = {0,5,0},
621         .transp = {0,0,0},      
622 #ifdef  CONFIG_LOGO_LINUX_BMP
623         .nonstd      = HAL_PIXEL_FORMAT_RGBA_8888,
624 #else
625         .nonstd      = HAL_PIXEL_FORMAT_RGB_565,   //(ypos<<20+xpos<<8+format) format
626 #endif
627         .grayscale   = 0,  //(ysize<<20+xsize<<8)
628         .activate    = FB_ACTIVATE_NOW,
629         .accel_flags = 0,
630         .vmode       = FB_VMODE_NONINTERLACED,
631 };
632
633 static struct fb_fix_screeninfo def_fix = {
634         .type            = FB_TYPE_PACKED_PIXELS,
635         .type_aux        = 0,
636         .xpanstep        = 1,
637         .ypanstep        = 1,
638         .ywrapstep       = 0,
639         .accel           = FB_ACCEL_NONE,
640         .visual          = FB_VISUAL_TRUECOLOR,
641                 
642 };
643
644
645 static int rk_fb_wait_for_vsync_thread(void *data)
646 {
647         struct rk_lcdc_device_driver  *dev_drv = data;
648         struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
649         struct fb_info *fbi = inf->fb[0];
650
651         while (!kthread_should_stop()) {
652                 ktime_t timestamp = dev_drv->vsync_info.timestamp;
653                 int ret = wait_event_interruptible(dev_drv->vsync_info.wait,
654                         !ktime_equal(timestamp, dev_drv->vsync_info.timestamp) &&
655                         dev_drv->vsync_info.active);
656
657                 if (!ret) {
658                         sysfs_notify(&fbi->dev->kobj, NULL, "vsync");
659                 }
660         }
661
662         return 0;
663 }
664
665 static ssize_t rk_fb_vsync_show(struct device *dev,
666                 struct device_attribute *attr, char *buf)
667 {
668         struct fb_info *fbi = dev_get_drvdata(dev);
669         struct rk_lcdc_device_driver * dev_drv = 
670                 (struct rk_lcdc_device_driver * )fbi->par;
671         return scnprintf(buf, PAGE_SIZE, "%llu\n",
672                         ktime_to_ns(dev_drv->vsync_info.timestamp));
673 }
674
675 static DEVICE_ATTR(vsync, S_IRUGO, rk_fb_vsync_show, NULL);
676
677
678 /*****************************************************************
679 this two function is for other module that in the kernel which
680 need show image directly through fb
681 fb_id:we have 4 fb here,default we use fb0 for ui display
682 *******************************************************************/
683 struct fb_info * rk_get_fb(int fb_id)
684 {
685     struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
686     struct fb_info *fb = inf->fb[fb_id];
687     return fb;
688 }
689 EXPORT_SYMBOL(rk_get_fb);
690
691 void rk_direct_fb_show(struct fb_info * fbi)
692 {
693     rk_fb_set_par(fbi);
694     rk_pan_display(&fbi->var, fbi);
695 }
696 EXPORT_SYMBOL(rk_direct_fb_show);
697
698
699
700 /******************************************
701 function:this function will be called by hdmi,when 
702               hdmi plug in/out
703 screen: the screen attached to hdmi
704 enable: 1,hdmi plug in,0,hdmi plug out
705 lcdc_id: the lcdc id the hdmi attached ,0 or 1
706 ******************************************/
707 int rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id)
708 {
709         struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
710         struct fb_info *info = NULL;
711         struct fb_info *pmy_info = NULL;
712         struct rk_lcdc_device_driver * dev_drv = NULL;
713         struct fb_var_screeninfo *pmy_var = NULL;      //var for primary screen
714         struct fb_var_screeninfo *hdmi_var    = NULL;
715         struct fb_fix_screeninfo *pmy_fix = NULL;
716         struct fb_fix_screeninfo *hdmi_fix    = NULL;
717         char name[6];
718         int ret;
719         int i;
720         int layer_id;
721
722 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) || defined(CONFIG_NO_DUAL_DISP)
723         rk29_backlight_set(0);
724 #endif
725         
726         sprintf(name, "lcdc%d",lcdc_id);
727         for(i = 0; i < inf->num_lcdc; i++)  //find the driver the display device connected to
728         {
729                 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
730                 {
731                         dev_drv = inf->lcdc_dev_drv[i];
732                         break;
733                 }
734         }
735
736         if(i == inf->num_lcdc)
737         {
738                 printk(KERN_ERR "%s driver not found!",name);
739                 return -ENODEV;
740                 
741         }
742
743         
744         if((lcdc_id == 0) || (inf->num_lcdc == 1))
745         {
746                 info = inf->fb[0];
747         }
748         else if((lcdc_id == 1)&&(inf->num_lcdc == 2))
749         {
750                 info = inf->fb[dev_drv->num_layer]; //the main fb of lcdc1
751         }
752
753         if(dev_drv->screen1) //device like rk2928 ,have only one lcdc but two outputs
754         {
755                 if(enable)
756                 {
757                         memcpy(dev_drv->screen1,screen,sizeof(rk_screen ));
758                         dev_drv->screen1->lcdc_id = 0; //connect screen1 to output interface 0
759                         dev_drv->screen1->screen_id = 1;
760                         dev_drv->screen0->lcdc_id = 1; //connect screen0 to output interface 1
761                         dev_drv->cur_screen = dev_drv->screen1;
762                         if(dev_drv->screen0->sscreen_get)
763                         {
764                                 dev_drv->screen0->sscreen_get(dev_drv->screen0,
765                                         dev_drv->cur_screen->hdmi_resolution);
766                         }
767                         if(dev_drv->screen0->sscreen_set)
768                         {
769                                 dev_drv->screen0->sscreen_set(dev_drv->screen0,enable);
770                         }
771                         
772                 }
773                 else
774                 {
775                         dev_drv->screen1->lcdc_id = 1; //connect screen1 to output interface 1
776                         dev_drv->screen0->lcdc_id = 0; //connect screen0 to output interface 0
777                         dev_drv->cur_screen = dev_drv->screen0;
778                         dev_drv->screen_ctr_info->set_screen_info(dev_drv->cur_screen,
779                         dev_drv->screen_ctr_info->lcd_info);
780                         
781                 }
782         }
783         else
784         {
785                 if(enable)
786                 {
787                         memcpy(dev_drv->cur_screen,screen,sizeof(rk_screen ));
788                 }
789         }
790
791         
792         layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
793         
794         if(!enable && !dev_drv->screen1) //only double lcdc device need to close
795         {
796                 if(dev_drv->layer_par[layer_id]->state) 
797                 {
798                         dev_drv->open(dev_drv,layer_id,enable); //disable the layer which attached to this fb
799                 }
800                 return 0;
801         }
802         
803         hdmi_var = &info->var;
804         hdmi_fix = &info->fix;
805         #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
806                 if(likely(inf->num_lcdc == 2))
807                 {
808                         pmy_var = &inf->fb[0]->var;
809                         pmy_fix = &inf->fb[0]->fix;
810                         hdmi_var->xres = pmy_var->xres;
811                         hdmi_var->yres = pmy_var->yres;
812                         hdmi_var->xres_virtual = pmy_var->xres_virtual;
813                         hdmi_var->yres_virtual = pmy_var->yres_virtual;
814                         hdmi_var->nonstd &= 0xffffff00;
815                         hdmi_var->nonstd |= (pmy_var->nonstd & 0xff); //use the same format as primary screen
816                 }
817                 else
818                 {
819                         printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!",__func__);
820                 }
821         #endif
822         hdmi_var->grayscale &= 0xff;
823         hdmi_var->grayscale |= (dev_drv->cur_screen->x_res<<8) + (dev_drv->cur_screen->y_res<<20);
824
825         if(dev_drv->screen1)  //device like rk2928,whic have one lcdc but two outputs
826         {
827         //      info->var.nonstd &= 0xff;
828         //      info->var.nonstd |= (dev_drv->cur_screen->xpos<<8) + (dev_drv->cur_screen->ypos<<20);
829         //      info->var.grayscale &= 0xff;
830         //      info->var.grayscale |= (dev_drv->cur_screen->x_res<<8) + (dev_drv->cur_screen->y_res<<20);
831                 dev_drv->screen1->xsize = dev_drv->cur_screen->x_res;
832                 dev_drv->screen1->ysize = dev_drv->cur_screen->y_res;
833                 dev_drv->screen1->xpos = 0;
834                 dev_drv->screen1->ypos = 0;
835         }
836         ret = info->fbops->fb_open(info,1);
837         ret = info->fbops->fb_set_par(info);
838         if(dev_drv->lcdc_hdmi_process)
839                 dev_drv->lcdc_hdmi_process(dev_drv,enable);
840
841         #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
842                 if(likely(inf->num_lcdc == 2))
843                 {
844                         pmy_info = inf->fb[0];
845                         pmy_info->fbops->fb_pan_display(pmy_var,pmy_info);
846                 }
847                 else
848                 {
849                         printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!",__func__);
850                 }
851         #elif defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
852                 info->fbops->fb_pan_display(hdmi_var,info);
853         #endif 
854
855 #if defined(CONFIG_NO_DUAL_DISP)  //close backlight for device whic do not support dual display
856         if(!enable)
857                 rk29_backlight_set(1);
858 #elif defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)  //close backlight for device whic do not support dual display
859         rk29_backlight_set(1);
860 #endif
861         return 0;
862
863 }
864
865
866
867
868 /******************************************
869 function:this function current only called by hdmi for 
870         scale the display
871 scale_x: scale rate of x resolution
872 scale_y: scale rate of y resolution
873 lcdc_id: the lcdc id the hdmi attached ,0 or 1
874 ******************************************/
875
876 int rk_fb_disp_scale(u8 scale_x, u8 scale_y,u8 lcdc_id)
877 {
878         struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
879         struct fb_info *info = NULL;
880         struct fb_var_screeninfo *var = NULL;
881         struct rk_lcdc_device_driver * dev_drv = NULL;
882         u16 screen_x,screen_y;
883         u16 xpos,ypos;
884         u16 xsize,ysize;
885         
886         char name[6];
887         int i;
888         sprintf(name, "lcdc%d",lcdc_id);
889         for(i = 0; i < inf->num_lcdc; i++)
890         {
891                 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
892                 {
893                         dev_drv = inf->lcdc_dev_drv[i];
894                         break;
895                 }
896         }
897
898         if(i == inf->num_lcdc)
899         {
900                 printk(KERN_ERR "%s driver not found!",name);
901                 return -ENODEV;
902                 
903         }
904
905         if((lcdc_id == 0) || (inf->num_lcdc == 1))
906         {
907                 info = inf->fb[0];
908         }
909         else if( (inf->num_lcdc == 2)&&(lcdc_id == 1))
910         {
911                 info = inf->fb[dev_drv->num_layer];
912         }
913
914         var = &info->var;
915         screen_x = dev_drv->cur_screen->x_res;
916         screen_y = dev_drv->cur_screen->y_res;
917         
918 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)||defined(CONFIG_NO_DUAL_DISP)
919         if(dev_drv->cur_screen->screen_id == 1){
920                 dev_drv->cur_screen->xpos = (screen_x-screen_x*scale_x/100)>>1;
921                 dev_drv->cur_screen->ypos = (screen_y-screen_y*scale_y/100)>>1;
922                 dev_drv->cur_screen->xsize = screen_x*scale_x/100;
923                 dev_drv->cur_screen->ysize = screen_y*scale_y/100;
924         }else
925 #endif
926         {
927                 xpos = (screen_x-screen_x*scale_x/100)>>1;
928                 ypos = (screen_y-screen_y*scale_y/100)>>1;
929                 xsize = screen_x*scale_x/100;
930                 ysize = screen_y*scale_y/100;
931                 var->nonstd &= 0xff;
932                 var->nonstd |= (xpos<<8) + (ypos<<20);
933                 var->grayscale &= 0xff;
934                 var->grayscale |= (xsize<<8) + (ysize<<20);     
935         }
936
937         info->fbops->fb_set_par(info);
938         return 0;
939         
940         
941 }
942
943 static int rk_request_fb_buffer(struct fb_info *fbi,int fb_id)
944 {
945         struct resource *res;
946         struct resource *mem;
947         int ret = 0;
948         struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
949         if (!strcmp(fbi->fix.id,"fb0"))
950         {
951                 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb0 buf");
952                 if (res == NULL)
953                 {
954                         dev_err(&g_fb_pdev->dev, "failed to get memory for fb0 \n");
955                         ret = -ENOENT;
956                 }
957                 fbi->fix.smem_start = res->start;
958                 fbi->fix.smem_len = res->end - res->start + 1;
959                 mem = request_mem_region(res->start, resource_size(res), g_fb_pdev->name);
960                 fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
961                 memset(fbi->screen_base, 0, fbi->fix.smem_len);
962                 printk("fb%d:phy:%lx>>vir:%p>>len:0x%x\n",fb_id,
963                 fbi->fix.smem_start,fbi->screen_base,fbi->fix.smem_len);
964         }
965         else
966         {       
967 #if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
968                 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb2 buf");
969                 if (res == NULL)
970                 {
971                         dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
972                         ret = -ENOENT;
973                 }
974                 fbi->fix.smem_start = res->start;
975                 fbi->fix.smem_len = res->end - res->start + 1;
976                 mem = request_mem_region(res->start, resource_size(res), g_fb_pdev->name);
977                 fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
978                 memset(fbi->screen_base, 0, fbi->fix.smem_len);
979 #else    //three buffer no need to copy
980                 fbi->fix.smem_start = fb_inf->fb[0]->fix.smem_start;
981                 fbi->fix.smem_len   = fb_inf->fb[0]->fix.smem_len;
982                 fbi->screen_base    = fb_inf->fb[0]->screen_base;
983 #endif
984                 printk("fb%d:phy:%lx>>vir:%p>>len:0x%x\n",fb_id,
985                         fbi->fix.smem_start,fbi->screen_base,fbi->fix.smem_len);        
986         }
987     return ret;
988 }
989
990 static int rk_release_fb_buffer(struct fb_info *fbi)
991 {
992         if(!fbi)
993         {
994                 printk("no need release null fb buffer!\n");
995                 return -EINVAL;
996         }
997         if(!strcmp(fbi->fix.id,"fb1")||!strcmp(fbi->fix.id,"fb3"))  //buffer for fb1 and fb3 are alloc by android
998                 return 0;
999         iounmap(fbi->screen_base);
1000         release_mem_region(fbi->fix.smem_start,fbi->fix.smem_len);
1001         return 0;
1002         
1003 }
1004 static int init_layer_par(struct rk_lcdc_device_driver *dev_drv)
1005 {
1006        int i;
1007        struct layer_par * def_par = NULL;
1008        int num_par = dev_drv->num_layer;
1009        for(i = 0; i < num_par; i++)
1010        {
1011                struct layer_par *par = NULL;
1012                par =  kzalloc(sizeof(struct layer_par), GFP_KERNEL);
1013                if(!par)
1014                {
1015                        printk(KERN_ERR "kzmalloc for layer_par fail!");
1016                        return   -ENOMEM;
1017                        
1018                }
1019                def_par = &dev_drv->def_layer_par[i];
1020                strcpy(par->name,def_par->name);
1021                par->id = def_par->id;
1022                par->support_3d = def_par->support_3d;
1023                dev_drv->layer_par[i] = par;
1024        }
1025                
1026        return 0;
1027        
1028        
1029 }
1030
1031
1032 static int init_lcdc_device_driver(struct rk_lcdc_device_driver *dev_drv,
1033         struct rk_lcdc_device_driver *def_drv,int id)
1034 {
1035         if(!def_drv)
1036         {
1037                 printk(KERN_ERR "default lcdc device driver is null!\n");
1038                 return -EINVAL;
1039         }
1040         if(!dev_drv)
1041         {
1042                 printk(KERN_ERR "lcdc device driver is null!\n");
1043                 return -EINVAL; 
1044         }
1045         sprintf(dev_drv->name, "lcdc%d",id);
1046         dev_drv->id             = id;
1047         dev_drv->open           = def_drv->open;
1048         dev_drv->init_lcdc      = def_drv->init_lcdc;
1049         dev_drv->ioctl          = def_drv->ioctl;
1050         dev_drv->blank          = def_drv->blank;
1051         dev_drv->set_par        = def_drv->set_par;
1052         dev_drv->pan_display    = def_drv->pan_display;
1053         dev_drv->suspend        = def_drv->suspend;
1054         dev_drv->resume         = def_drv->resume;
1055         dev_drv->load_screen    = def_drv->load_screen;
1056         dev_drv->def_layer_par  = def_drv->def_layer_par;
1057         dev_drv->num_layer      = def_drv->num_layer;
1058         dev_drv->get_layer_state= def_drv->get_layer_state;
1059         dev_drv->get_disp_info  = def_drv->get_disp_info;
1060         dev_drv->ovl_mgr        = def_drv->ovl_mgr;
1061         dev_drv->fps_mgr        = def_drv->fps_mgr;
1062         if(def_drv->fb_get_layer)
1063                 dev_drv->fb_get_layer   = def_drv->fb_get_layer;
1064         if(def_drv->fb_layer_remap)
1065                 dev_drv->fb_layer_remap = def_drv->fb_layer_remap;
1066         if(def_drv->set_dsp_lut)
1067                 dev_drv->set_dsp_lut    = def_drv->set_dsp_lut;
1068         if(def_drv->read_dsp_lut)
1069                 dev_drv->read_dsp_lut   = def_drv->read_dsp_lut;
1070         if(def_drv->lcdc_hdmi_process)
1071                 dev_drv->lcdc_hdmi_process = def_drv->lcdc_hdmi_process;
1072         init_layer_par(dev_drv);
1073         init_completion(&dev_drv->frame_done);
1074         spin_lock_init(&dev_drv->cpl_lock);
1075         mutex_init(&dev_drv->fb_win_id_mutex);
1076         dev_drv->fb_layer_remap(dev_drv,FB_DEFAULT_ORDER); //102
1077         dev_drv->first_frame = 1;
1078         
1079         return 0;
1080 }
1081  
1082 #ifdef CONFIG_LOGO_LINUX_BMP
1083 static struct linux_logo *bmp_logo;
1084 static int fb_prepare_bmp_logo(struct fb_info *info, int rotate)
1085 {
1086         bmp_logo = fb_find_logo(24);
1087         if (bmp_logo == NULL) {
1088                 printk("%s error\n", __func__);
1089                 return 0;
1090         }
1091         return 1;
1092 }
1093
1094 static void fb_show_bmp_logo(struct fb_info *info, int rotate)
1095 {
1096         unsigned char *src=bmp_logo->data;
1097         unsigned char *dst=info->screen_base;
1098         int i;
1099         unsigned int Needwidth=(*(src-24)<<8)|(*(src-23));
1100         unsigned int Needheight=(*(src-22)<<8)|(*(src-21));
1101                 
1102         for(i=0;i<Needheight;i++)
1103                 memcpy(dst+info->var.xres*i*4, src+bmp_logo->width*i*4, Needwidth*4);
1104         
1105 }
1106 #endif
1107
1108 int rk_fb_register(struct rk_lcdc_device_driver *dev_drv,
1109         struct rk_lcdc_device_driver *def_drv,int id)
1110 {
1111         struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
1112         struct fb_info *fbi;
1113         int i=0,ret = 0;
1114         int lcdc_id = 0;
1115         if(NULL == dev_drv)
1116         {
1117                 printk("null lcdc device driver?");
1118                 return -ENOENT;
1119         }
1120         for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++)
1121         {
1122                 if(NULL==fb_inf->lcdc_dev_drv[i])
1123                 {
1124                         fb_inf->lcdc_dev_drv[i] = dev_drv;
1125                         fb_inf->lcdc_dev_drv[i]->id = id;
1126                         fb_inf->num_lcdc++;
1127                         break;
1128                 }
1129         }
1130         if(i==RK30_MAX_LCDC_SUPPORT)
1131         {
1132                 printk("rk_fb_register lcdc out of support %d",i);
1133                 return -ENOENT;
1134         }
1135         lcdc_id = i;
1136         init_lcdc_device_driver(dev_drv, def_drv,id);
1137         
1138         dev_drv->init_lcdc(dev_drv);
1139         /************fb set,one layer one fb ***********/
1140         dev_drv->fb_index_base = fb_inf->num_fb;
1141         for(i=0;i<dev_drv->num_layer;i++)
1142         {
1143                 fbi= framebuffer_alloc(0, &g_fb_pdev->dev);
1144                 if(!fbi)
1145                 {
1146                     dev_err(&g_fb_pdev->dev,">> fb framebuffer_alloc fail!");
1147                     fbi = NULL;
1148                     ret = -ENOMEM;
1149                 }
1150                 fbi->par = dev_drv;
1151                 fbi->var = def_var;
1152                 fbi->fix = def_fix;
1153                 sprintf(fbi->fix.id,"fb%d",fb_inf->num_fb);
1154                 fbi->var.xres = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->x_res;
1155                 fbi->var.yres = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->y_res;
1156                 fbi->var.grayscale |= (fbi->var.xres<<8) + (fbi->var.yres<<20);
1157 #ifdef  CONFIG_LOGO_LINUX_BMP
1158                 fbi->var.bits_per_pixel = 32; 
1159 #else
1160                 fbi->var.bits_per_pixel = 16; 
1161 #endif
1162                 fbi->fix.line_length  = (fbi->var.xres)*(fbi->var.bits_per_pixel>>3);
1163                 fbi->var.xres_virtual = fbi->var.xres;
1164                 fbi->var.yres_virtual = fbi->var.yres;
1165                 fbi->var.width =  fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->width;
1166                 fbi->var.height = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->height;
1167                 fbi->var.pixclock = fb_inf->lcdc_dev_drv[lcdc_id]->pixclock;
1168                 fbi->var.left_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->left_margin;
1169                 fbi->var.right_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->right_margin;
1170                 fbi->var.upper_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->upper_margin;
1171                 fbi->var.lower_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->lower_margin;
1172                 fbi->var.vsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->vsync_len;
1173                 fbi->var.hsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->hsync_len;
1174                 fbi->fbops                       = &fb_ops;
1175                 fbi->flags                       = FBINFO_FLAG_DEFAULT;
1176                 fbi->pseudo_palette  = fb_inf->lcdc_dev_drv[lcdc_id]->layer_par[i]->pseudo_pal;
1177                 if (i == 0) //only alloc memory for main fb
1178                 {
1179                         rk_request_fb_buffer(fbi,fb_inf->num_fb);
1180                 }
1181                 ret = register_framebuffer(fbi);
1182                 if(ret<0)
1183                 {
1184                     printk("%s>>fb%d register_framebuffer fail!\n",__func__,fb_inf->num_fb);
1185                     ret = -EINVAL;
1186                 }
1187                 rkfb_create_sysfs(fbi);
1188
1189                 if(i == 0)
1190                 {
1191                         init_waitqueue_head(&dev_drv->vsync_info.wait);
1192                         ret = device_create_file(fbi->dev,&dev_attr_vsync);
1193                         if (ret) 
1194                         {
1195                                 dev_err(fbi->dev, "failed to create vsync file\n");
1196                         }
1197                         dev_drv->vsync_info.thread = kthread_run(rk_fb_wait_for_vsync_thread,
1198                                 dev_drv, "fb-vsync");
1199
1200                         
1201                         if (dev_drv->vsync_info.thread == ERR_PTR(-ENOMEM)) 
1202                         {
1203                                 dev_err(fbi->dev, "failed to run vsync thread\n");
1204                                 dev_drv->vsync_info.thread = NULL;
1205                         }
1206                         dev_drv->vsync_info.active = 1;
1207                 }
1208                 fb_inf->fb[fb_inf->num_fb] = fbi;
1209                 printk("%s>>>>>%s\n",__func__,fb_inf->fb[fb_inf->num_fb]->fix.id);
1210                 fb_inf->num_fb++;       
1211         }
1212 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
1213     if(dev_drv->screen_ctr_info->prop == PRMRY) //show logo for primary display device
1214     {
1215             fb_inf->fb[0]->fbops->fb_open(fb_inf->fb[0],1);
1216             fb_inf->fb[0]->fbops->fb_set_par(fb_inf->fb[0]);
1217
1218 #if  defined(CONFIG_LOGO_LINUX_BMP)
1219                 if(fb_prepare_bmp_logo(fb_inf->fb[0], FB_ROTATE_UR)) {
1220                         /* Start display and show logo on boot */
1221                         fb_set_cmap(&fb_inf->fb[0]->cmap, fb_inf->fb[0]);
1222                         fb_show_bmp_logo(fb_inf->fb[0], FB_ROTATE_UR);
1223                         fb_inf->fb[0]->fbops->fb_pan_display(&(fb_inf->fb[0]->var), fb_inf->fb[0]);
1224                 }
1225 #else
1226                 if(fb_prepare_logo(fb_inf->fb[0], FB_ROTATE_UR)) {
1227                         /* Start display and show logo on boot */
1228                         fb_set_cmap(&fb_inf->fb[0]->cmap, fb_inf->fb[0]);
1229                         fb_show_logo(fb_inf->fb[0], FB_ROTATE_UR);
1230                         fb_inf->fb[0]->fbops->fb_pan_display(&(fb_inf->fb[0]->var), fb_inf->fb[0]);
1231                 }
1232 #endif
1233                 
1234     }
1235 #endif
1236         return 0;
1237         
1238         
1239 }
1240 int rk_fb_unregister(struct rk_lcdc_device_driver *dev_drv)
1241 {
1242
1243         struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
1244         struct fb_info *fbi;
1245         int fb_index_base = dev_drv->fb_index_base;
1246         int fb_num = dev_drv->num_layer;
1247         int i=0;
1248         if(NULL == dev_drv)
1249         {
1250                 printk(" no need to unregister null lcdc device driver!\n");
1251                 return -ENOENT;
1252         }
1253
1254         for(i = 0; i < fb_num; i++)
1255         {
1256                 kfree(dev_drv->layer_par[i]);
1257         }
1258
1259         for(i=fb_index_base;i<(fb_index_base+fb_num);i++)
1260         {
1261                 fbi = fb_inf->fb[i];
1262                 unregister_framebuffer(fbi);
1263                 //rk_release_fb_buffer(fbi);
1264                 framebuffer_release(fbi);       
1265         }
1266         fb_inf->lcdc_dev_drv[dev_drv->id]= NULL;
1267         fb_inf->num_lcdc--;
1268
1269         return 0;
1270 }
1271
1272
1273
1274 #ifdef CONFIG_HAS_EARLYSUSPEND
1275 struct suspend_info {
1276         struct early_suspend early_suspend;
1277         struct rk_fb_inf *inf;
1278 };
1279
1280 static void rkfb_early_suspend(struct early_suspend *h)
1281 {
1282         struct suspend_info *info = container_of(h, struct suspend_info,
1283                                                 early_suspend);
1284         struct rk_fb_inf *inf = info->inf;
1285         int i;
1286         for(i = 0; i < inf->num_lcdc; i++)
1287         {
1288                 if (!inf->lcdc_dev_drv[i])
1289                         continue;
1290                         
1291                 inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
1292         }
1293 }
1294 static void rkfb_early_resume(struct early_suspend *h)
1295 {
1296         struct suspend_info *info = container_of(h, struct suspend_info,
1297                                                 early_suspend);
1298         struct rk_fb_inf *inf = info->inf;
1299         int i;
1300         for(i = 0; i < inf->num_lcdc; i++)
1301         {
1302                 if (!inf->lcdc_dev_drv[i])
1303                         continue;
1304                 
1305                 inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]);            // data out
1306         }
1307
1308 }
1309
1310
1311
1312 static struct suspend_info suspend_info = {
1313         .early_suspend.suspend = rkfb_early_suspend,
1314         .early_suspend.resume = rkfb_early_resume,
1315         .early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
1316 };
1317 #endif
1318
1319 static int __devinit rk_fb_probe (struct platform_device *pdev)
1320 {
1321         struct rk_fb_inf *fb_inf = NULL;
1322         int ret = 0;
1323         g_fb_pdev=pdev;
1324         /* Malloc rk_fb_inf and set it to pdev for drvdata */
1325         fb_inf = kzalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
1326         if(!fb_inf)
1327         {
1328                 dev_err(&pdev->dev, ">>fb inf kmalloc fail!");
1329                 ret = -ENOMEM;
1330         }
1331         platform_set_drvdata(pdev,fb_inf);
1332
1333 #ifdef CONFIG_HAS_EARLYSUSPEND
1334         suspend_info.inf = fb_inf;
1335         register_early_suspend(&suspend_info.early_suspend);
1336 #endif
1337         printk("rk fb probe ok!\n");
1338     return 0;
1339 }
1340
1341 static int __devexit rk_fb_remove(struct platform_device *pdev)
1342 {
1343         struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
1344         kfree(fb_inf);
1345         platform_set_drvdata(pdev, NULL);
1346         return 0;
1347 }
1348
1349 static void rk_fb_shutdown(struct platform_device *pdev)
1350 {
1351         struct rk_fb_inf *inf = platform_get_drvdata(pdev);
1352         int i;
1353         for(i = 0; i < inf->num_lcdc; i++)
1354         {
1355                 if (!inf->lcdc_dev_drv[i])
1356                         continue;
1357
1358                 if(inf->lcdc_dev_drv[i]->vsync_info.thread)
1359                         kthread_stop(inf->lcdc_dev_drv[i]->vsync_info.thread);
1360         }
1361 //      kfree(fb_inf);
1362 //      platform_set_drvdata(pdev, NULL);
1363 #ifdef CONFIG_HAS_EARLYSUSPEND
1364         unregister_early_suspend(&suspend_info.early_suspend);
1365 #endif
1366 }
1367
1368 static struct platform_driver rk_fb_driver = {
1369         .probe          = rk_fb_probe,
1370         .remove         = __devexit_p(rk_fb_remove),
1371         .driver         = {
1372                 .name   = "rk-fb",
1373                 .owner  = THIS_MODULE,
1374         },
1375         .shutdown   = rk_fb_shutdown,
1376 };
1377
1378 static int __init rk_fb_init(void)
1379 {
1380     return platform_driver_register(&rk_fb_driver);
1381 }
1382
1383 static void __exit rk_fb_exit(void)
1384 {
1385     platform_driver_unregister(&rk_fb_driver);
1386 }
1387
1388 subsys_initcall_sync(rk_fb_init);
1389 module_exit(rk_fb_exit);
1390