2 * drivers/video/rockchip/rk_fb.c
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.
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.
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/string.h>
22 #include <linux/slab.h>
23 #include <linux/delay.h>
24 #include <linux/device.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>
35 #define fbprintk(msg...) printk(msg);
37 #define fbprintk(msg...)
41 #define CHK_SUSPEND(drv) \
42 if(atomic_dec_and_test(&drv->in_suspend)) { \
43 printk(">>>>>> fb is in suspend! return! \n"); \
47 #define CHK_SUSPEND(inf)
50 static struct platform_device *g_fb_pdev;
52 static struct rk_fb_rgb def_rgb_16 = {
53 red: { offset: 11, length: 5, },
54 green: { offset: 5, length: 6, },
55 blue: { offset: 0, length: 5, },
56 transp: { offset: 0, length: 0, },
60 /***************************************************************************
61 fb0-----------lcdc0------------win1 for ui
62 fb1-----------lcdc0------------win0 for video,win0 support 3d display
63 fb2-----------lcdc1------------win1 for ui
64 fb3-----------lcdc1-------------win0 for video ,win0 support 3d display
66 defautl:we alloc three buffer,one for fb0 and fb2 display ui,one for ipp rotate
67 fb1 and fb3 are used for video play,the buffer is alloc by android,and
68 pass the phy addr to fix.smem_start by ioctl
69 ****************************************************************************/
71 int get_fb_layer_id(struct fb_fix_screeninfo *fix)
74 if(!strcmp(fix->id,"fb1")||!strcmp(fix->id,"fb3"))
78 else if(!strcmp(fix->id,"fb0")||!strcmp(fix->id,"fb2"))
84 printk(KERN_ERR "unsupported %s",fix->id);
91 /**********************************************************************
93 name: lcdc device name ,lcdc0 , lcdc1
94 ***********************************************************************/
95 struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name)
97 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
99 for( i = 0; i < inf->num_lcdc; i++)
101 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
104 return inf->lcdc_dev_drv[i];
107 static int rk_fb_open(struct fb_info *info,int user)
109 struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
111 CHK_SUSPEND(dev_drv);
112 layer_id = get_fb_layer_id(&info->fix);
113 dev_drv->open(dev_drv,layer_id,1);
119 static int rk_fb_close(struct fb_info *info,int user)
121 struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
123 CHK_SUSPEND(dev_drv);
124 layer_id = get_fb_layer_id(&info->fix);
125 dev_drv->open(dev_drv,layer_id,0);
130 static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
132 struct fb_fix_screeninfo *fix = &info->fix;
133 struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
134 struct layer_par *par = NULL;
136 u32 xoffset = var->xoffset; // offset from virtual to visible
137 u32 yoffset = var->yoffset;
138 u32 xvir = var->xres_virtual;
139 u8 data_format = var->nonstd&0xff;
140 layer_id = get_fb_layer_id(fix);
141 CHK_SUSPEND(dev_drv);
148 par = dev_drv->layer_par[layer_id];
153 par->y_offset = (yoffset*xvir + xoffset)*4;
156 par->y_offset = (yoffset*xvir + xoffset)*3;
159 par->y_offset = (yoffset*xvir + xoffset)*2;
162 par->y_offset = yoffset*xvir + xoffset;
163 par->c_offset = par->y_offset;
166 par->y_offset = yoffset*xvir + xoffset;
167 par->c_offset = (yoffset>>1)*xvir + xoffset;
169 case YUV444 : // yuv444
170 par->y_offset = yoffset*xvir + xoffset;
171 par->c_offset = yoffset*2*xvir +(xoffset<<1);
174 printk("un supported format:0x%x\n",data_format);
178 dev_drv->pan_display(dev_drv,layer_id);
182 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg)
184 struct rk_fb_inf *inf = dev_get_drvdata(info->device);
185 struct fb_fix_screeninfo *fix = &info->fix;
186 struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
188 void __user *argp = (void __user *)arg;
189 fbprintk(">>>>>> %s : cmd:0x%x \n",__FUNCTION__,cmd);
191 CHK_SUSPEND(dev_drv);
194 case FBIOPUT_FBPHYADD:
195 return info->fix.smem_start;
196 case FB1_IOCTL_SET_YUV_ADDR: //when in video mode, buff alloc by android
197 if((!strcmp(fix->id,"fb1"))||(!strcmp(fix->id,"fb3")))
199 if (copy_from_user(yuv_phy, argp, 8))
201 info->fix.smem_start = yuv_phy[0]; //four y
202 info->fix.mmio_start = yuv_phy[1]; //four uv
205 case FBIOGET_OVERLAY_STATE:
206 return inf->video_mode;
207 case FBIOGET_SCREEN_STATE:
208 case FBIOPUT_SET_CURSOR_EN:
209 case FBIOPUT_SET_CURSOR_POS:
210 case FBIOPUT_SET_CURSOR_IMG:
211 case FBIOPUT_SET_CURSOR_CMAP:
212 case FBIOPUT_GET_CURSOR_RESOLUTION:
213 case FBIOPUT_GET_CURSOR_EN:
214 case FB0_IOCTL_STOP_TIMER_FLUSH: //stop timer flush mcu panel after android is runing
217 case FBIOGET_IDLEFBUff_16OR32:
218 case FBIOSET_COMPOSE_LAYER_COUNTS:
219 case FBIOGET_COMPOSE_LAYER_COUNTS:
221 dev_drv->ioctl(dev_drv,cmd,arg,0);
227 static int rk_fb_blank(int blank_mode, struct fb_info *info)
229 struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
230 struct fb_fix_screeninfo *fix = &info->fix;
232 CHK_SUSPEND(dev_drv);
233 layer_id = get_fb_layer_id(fix);
239 dev_drv->blank(dev_drv,layer_id,blank_mode);
244 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
246 struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
247 CHK_SUSPEND(dev_drv);
249 if( 0==var->xres_virtual || 0==var->yres_virtual ||
250 0==var->xres || 0==var->yres || var->xres<16 ||
251 ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) )
253 printk(">>>>>> fb_check_var fail 1!!! \n");
254 printk(">>>>>> 0==%d || 0==%d ", var->xres_virtual,var->yres_virtual);
255 printk("0==%d || 0==%d || %d<16 || ", var->xres,var->yres,var->xres<16);
256 printk("bits_per_pixel=%d \n", var->bits_per_pixel);
260 if( (var->xoffset+var->xres)>var->xres_virtual ||
261 (var->yoffset+var->yres)>var->yres_virtual*2 )
263 printk(">>>>>> fb_check_var fail 2!!! \n");
264 printk(">>>>>> (%d+%d)>%d || ", var->xoffset,var->xres,var->xres_virtual);
265 printk("(%d+%d)>%d || ", var->yoffset,var->yres,var->yres_virtual);
270 switch(var->nonstd&0x0f)
273 switch(var->bits_per_pixel)
276 var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1);
277 var->xres = (var->xres + 0x1) & (~0x1);
278 var->xoffset = (var->xoffset) & (~0x1);
281 var->bits_per_pixel = 32;
284 var->nonstd &= ~0xc0; //not support I2P in this format
287 var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
288 var->xres = (var->xres + 0x3) & (~0x3);
289 var->xoffset = (var->xoffset) & (~0x3);
292 var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
293 var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1);
294 var->xres = (var->xres + 0x3) & (~0x3);
295 var->yres = (var->yres + 0x1) & (~0x1);
296 var->xoffset = (var->xoffset) & (~0x3);
297 var->yoffset = (var->yoffset) & (~0x1);
300 var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
301 var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1);
302 var->xres = (var->xres + 0x3) & (~0x3);
303 var->yres = (var->yres + 0x1) & (~0x1);
304 var->xoffset = (var->xoffset) & (~0x3);
305 var->yoffset = (var->yoffset) & (~0x1);
306 var->nonstd &= ~0xc0; //not support I2P in this format
310 var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
311 var->xres = (var->xres + 0x3) & (~0x3);
312 var->xoffset = (var->xoffset) & (~0x3);
313 var->nonstd &= ~0xc0; //not support I2P in this format
316 printk(">>>>>> fb1 var->nonstd=%d is invalid! \n", var->nonstd);
324 static int rk_fb_set_par(struct fb_info *info)
326 struct fb_var_screeninfo *var = &info->var;
327 struct fb_fix_screeninfo *fix = &info->fix;
328 struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
329 struct layer_par *par = NULL;
330 rk_screen *screen =dev_drv->screen;
332 u32 cblen = 0,crlen = 0;
333 u16 xsize =0,ysize = 0; //winx display window height/width --->LCDC_WINx_DSP_INFO
334 u32 xoffset = var->xoffset; // offset from virtual to visible
335 u32 yoffset = var->yoffset; //resolution
336 u16 xpos = (var->nonstd>>8) & 0xfff; //visiable pos in panel
337 u16 ypos = (var->nonstd>>20) & 0xfff;
338 u32 xvir = var->xres_virtual;
339 u32 yvir = var->yres_virtual;
340 u8 data_format = var->nonstd&0xff;
341 var->pixclock = dev_drv->pixclock;
342 CHK_SUSPEND(dev_drv);
343 layer_id = get_fb_layer_id(fix);
350 par = dev_drv->layer_par[layer_id];
352 if((!strcmp(fix->id,"fb0"))||(!strcmp(fix->id,"fb2"))) //four ui
354 xsize = screen->x_res;
355 ysize = screen->y_res;
357 else if((!strcmp(fix->id,"fb1"))||(!strcmp(fix->id,"fb3")))
359 xsize = (var->grayscale>>8) & 0xfff; //visiable size in panel ,for vide0
360 ysize = (var->grayscale>>20) & 0xfff;
363 /* calculate y_offset,c_offset,line_length,cblen and crlen */
367 case HAL_PIXEL_FORMAT_RGBA_8888 : // rgb
368 case HAL_PIXEL_FORMAT_RGBX_8888:
369 par->format = ARGB888;
370 fix->line_length = 4 * xvir;
371 par->y_offset = (yoffset*xvir + xoffset)*4;
373 case HAL_PIXEL_FORMAT_RGB_888 :
374 par->format = RGB888;
375 fix->line_length = 3 * xvir;
376 par->y_offset = (yoffset*xvir + xoffset)*3;
378 case HAL_PIXEL_FORMAT_RGB_565: //RGB565
379 par->format = RGB565;
380 fix->line_length = 2 * xvir;
381 par->y_offset = (yoffset*xvir + xoffset)*2;
383 case HAL_PIXEL_FORMAT_YCbCr_422_SP : // yuv422
384 par->format = YUV422;
385 fix->line_length = xvir;
386 cblen = crlen = (xvir*yvir)>>1;
387 par->y_offset = yoffset*xvir + xoffset;
388 par->c_offset = par->y_offset;
390 case HAL_PIXEL_FORMAT_YCrCb_NV12 : // YUV420---uvuvuv
391 par->format = YUV420;
392 fix->line_length = xvir;
393 cblen = crlen = (xvir*yvir)>>2;
394 par->y_offset = yoffset*xvir + xoffset;
395 par->c_offset = (yoffset>>1)*xvir + xoffset;
397 case HAL_PIXEL_FORMAT_YCrCb_444 : // yuv444
399 fix->line_length = xvir<<2;
400 par->y_offset = yoffset*xvir + xoffset;
401 par->c_offset = yoffset*2*xvir +(xoffset<<1);
402 cblen = crlen = (xvir*yvir);
405 printk("un supported format:0x%x\n",data_format);
409 switch(var->bits_per_pixel)
412 par->format = ARGB888;
413 fix->line_length = 4 * xvir;
414 par->y_offset = (yoffset*xvir + xoffset)*4;
417 par->format = RGB565;
418 fix->line_length = 2 * xvir;
419 par->y_offset = (yoffset*xvir + xoffset)*2;
430 par->smem_start =fix->smem_start;
431 par->cbr_start = fix->mmio_start;
432 par->xact = var->xres; //winx active window height,is a part of vir
433 par->yact = var->yres;
434 par->xvir = var->xres_virtual; // virtual resolution stride --->LCDC_WINx_VIR
435 par->yvir = var->yres_virtual;
436 dev_drv->set_par(dev_drv,layer_id);
441 static inline unsigned int chan_to_field(unsigned int chan,
442 struct fb_bitfield *bf)
445 chan >>= 16 - bf->length;
446 return chan << bf->offset;
449 static int fb_setcolreg(unsigned regno,
450 unsigned red, unsigned green, unsigned blue,
451 unsigned transp, struct fb_info *info)
455 switch (info->fix.visual) {
456 case FB_VISUAL_TRUECOLOR:
457 /* true-colour, use pseudo-palette */
459 u32 *pal = info->pseudo_palette;
460 val = chan_to_field(red, &info->var.red);
461 val |= chan_to_field(green, &info->var.green);
462 val |= chan_to_field(blue, &info->var.blue);
467 return -1; /* unknown type */
473 static struct fb_ops fb_ops = {
474 .owner = THIS_MODULE,
475 .fb_open = rk_fb_open,
476 .fb_release = rk_fb_close,
477 .fb_check_var = rk_fb_check_var,
478 .fb_set_par = rk_fb_set_par,
479 .fb_blank = rk_fb_blank,
480 .fb_ioctl = rk_fb_ioctl,
481 .fb_pan_display = rk_pan_display,
482 .fb_setcolreg = fb_setcolreg,
483 .fb_fillrect = cfb_fillrect,
484 .fb_copyarea = cfb_copyarea,
485 .fb_imageblit = cfb_imageblit,
490 static struct fb_var_screeninfo def_var = {
491 .red = {11,5,0},//default set to rgb565,the boot logo is rgb565
495 .nonstd = HAL_PIXEL_FORMAT_RGB_565, //(ypos<<20+xpos<<8+format) format
496 .grayscale = 0, //(ysize<<20+xsize<<8)
497 .activate = FB_ACTIVATE_NOW,
499 .vmode = FB_VMODE_NONINTERLACED,
502 static struct fb_fix_screeninfo def_fix = {
503 .type = FB_TYPE_PACKED_PIXELS,
508 .accel = FB_ACCEL_NONE,
509 .visual = FB_VISUAL_TRUECOLOR,
514 /*****************************************************************
515 this two function is for other module that in the kernel which
516 need show image directly through fb
517 fb_id:we have 4 fb here,default we use fb0 for ui display
518 *******************************************************************/
519 struct fb_info * rk_get_fb(int fb_id)
521 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
522 struct fb_info *fb = inf->fb[fb_id];
525 EXPORT_SYMBOL(rk_get_fb);
527 void rk_direct_fb_show(struct fb_info * fbi)
530 rk_pan_display(&fbi->var, fbi);
532 EXPORT_SYMBOL(rk_direct_fb_show);
534 static int rk_request_fb_buffer(struct fb_info *fbi,int fb_id)
536 struct resource *res;
537 struct resource *mem;
542 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb0 buf");
545 dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
548 fbi->fix.smem_start = res->start;
549 fbi->fix.smem_len = res->end - res->start + 1;
550 mem = request_mem_region(res->start, resource_size(res), g_fb_pdev->name);
551 fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
552 memset(fbi->screen_base, 0, fbi->fix.smem_len);
553 printk("fb%d:phy:%lx>>vir:%p>>len:0x%x\n",fb_id,
554 fbi->fix.smem_start,fbi->screen_base,fbi->fix.smem_len);
555 #ifdef CONFIG_FB_WORK_IPP // alloc ipp buf for rotate
556 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "ipp buf");
559 dev_err(&g_fb_pdev->dev, "failed to get win1 ipp memory \n");
562 fbi->fix.mmio_start = res->start;
563 fbi->fix.mmio_len = res->end - res->start + 1;
567 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb2 buf");
570 dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
573 fbi->fix.smem_start = res->start;
574 fbi->fix.smem_len = res->end - res->start + 1;
575 mem = request_mem_region(res->start, resource_size(res), g_fb_pdev->name);
576 fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
577 memset(fbi->screen_base, 0, fbi->fix.smem_len);
578 printk("fb%d:phy:%lx>>vir:%p>>len:0x%x\n",fb_id,
579 fbi->fix.smem_start,fbi->screen_base,fbi->fix.smem_len);
588 static int rk_release_fb_buffer(struct fb_info *fbi)
592 printk("no need release null fb buffer!\n");
595 if(!strcmp(fbi->fix.id,"fb1")||!strcmp(fbi->fix.id,"fb3")) //buffer for fb1 and fb3 are alloc by android
597 iounmap(fbi->screen_base);
598 release_mem_region(fbi->fix.smem_start,fbi->fix.smem_len);
602 static int init_layer_par(struct rk_lcdc_device_driver *dev_drv)
605 struct layer_par * def_par = NULL;
606 int num_par = dev_drv->num_layer;
607 for(i = 0; i < num_par; i++)
609 struct layer_par *par = NULL;
610 par = kzalloc(sizeof(struct layer_par), GFP_KERNEL);
613 printk(KERN_ERR "kzmalloc for layer_par fail!");
617 def_par = &dev_drv->def_layer_par[i];
618 strcpy(par->name,def_par->name);
619 par->id = def_par->id;
620 par->support_3d = def_par->support_3d;
621 dev_drv->layer_par[i] = par;
630 static int init_lcdc_device_driver(struct rk_lcdc_device_driver *dev_drv,
631 struct rk_lcdc_device_driver *def_drv,int id)
635 printk(KERN_ERR "default lcdc device driver is null!\n");
640 printk(KERN_ERR "lcdc device driver is null!\n");
643 sprintf(dev_drv->name, "lcdc%d",id);
644 dev_drv->open = def_drv->open;
645 dev_drv->init_lcdc = def_drv->init_lcdc;
646 dev_drv->ioctl = def_drv->ioctl;
647 dev_drv->blank = def_drv->blank;
648 dev_drv->set_par = def_drv->set_par;
649 dev_drv->pan_display = def_drv->pan_display;
650 dev_drv->suspend = def_drv->suspend;
651 dev_drv->resume = def_drv->resume;
652 dev_drv->load_screen = def_drv->load_screen;
653 dev_drv->def_layer_par = def_drv->def_layer_par;
654 dev_drv->num_layer = def_drv->num_layer;
655 init_layer_par(dev_drv);
656 init_completion(&dev_drv->frame_done);
657 spin_lock_init(&dev_drv->cpl_lock);
658 dev_drv->first_frame = 1;
663 int rk_fb_register(struct rk_lcdc_device_driver *dev_drv,
664 struct rk_lcdc_device_driver *def_drv,int id)
666 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
672 printk("null lcdc device driver?");
675 for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++)
677 if(NULL==fb_inf->lcdc_dev_drv[i])
679 fb_inf->lcdc_dev_drv[i] = dev_drv;
680 fb_inf->lcdc_dev_drv[i]->id = i;
685 if(i==RK30_MAX_LCDC_SUPPORT)
687 printk("rk_fb_register lcdc out of support %d",i);
691 init_lcdc_device_driver(dev_drv, def_drv,id);
692 set_lcd_info(dev_drv->screen, fb_inf->mach_info->lcd_info);
693 dev_drv->init_lcdc(dev_drv);
694 dev_drv->load_screen(dev_drv,1);
695 /************fb set,one layer one fb ***********/
696 dev_drv->fb_index_base = fb_inf->num_fb;
697 for(i=0;i<dev_drv->num_layer;i++)
699 fbi= framebuffer_alloc(0, &g_fb_pdev->dev);
702 dev_err(&g_fb_pdev->dev,">> fb framebuffer_alloc fail!");
709 sprintf(fbi->fix.id,"fb%d",fb_inf->num_fb);
710 fbi->var.xres = fb_inf->lcdc_dev_drv[lcdc_id]->screen->x_res;
711 fbi->var.yres = fb_inf->lcdc_dev_drv[lcdc_id]->screen->y_res;
712 fbi->var.bits_per_pixel = 16;
713 fbi->var.xres_virtual = fb_inf->lcdc_dev_drv[lcdc_id]->screen->x_res;
714 fbi->var.yres_virtual = fb_inf->lcdc_dev_drv[lcdc_id]->screen->y_res;
715 fbi->var.width = fb_inf->lcdc_dev_drv[lcdc_id]->screen->width;
716 fbi->var.height = fb_inf->lcdc_dev_drv[lcdc_id]->screen->height;
717 fbi->var.pixclock =fb_inf->lcdc_dev_drv[lcdc_id]->pixclock;
718 fbi->var.left_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen->left_margin;
719 fbi->var.right_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen->right_margin;
720 fbi->var.upper_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen->upper_margin;
721 fbi->var.lower_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen->lower_margin;
722 fbi->var.vsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->screen->vsync_len;
723 fbi->var.hsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->screen->hsync_len;
724 fbi->fbops = &fb_ops;
725 fbi->flags = FBINFO_FLAG_DEFAULT;
726 fbi->pseudo_palette = fb_inf->lcdc_dev_drv[lcdc_id]->layer_par[i]->pseudo_pal;
727 rk_request_fb_buffer(fbi,fb_inf->num_fb);
728 ret = register_framebuffer(fbi);
731 printk("%s>>fb%d register_framebuffer fail!\n",__func__,fb_inf->num_fb);
734 rkfb_create_sysfs(fbi);
735 fb_inf->fb[fb_inf->num_fb] = fbi;
736 printk("%s>>>>>%s\n",__func__,fb_inf->fb[fb_inf->num_fb]->fix.id);
739 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
740 fb_inf->fb[fb_inf->num_fb-2]->fbops->fb_set_par(fb_inf->fb[fb_inf->num_fb-2]);
741 if(fb_prepare_logo(fb_inf->fb[fb_inf->num_fb-2], FB_ROTATE_UR)) {
742 /* Start display and show logo on boot */
743 fb_set_cmap(&fb_inf->fb[fb_inf->num_fb-2]->cmap, fb_inf->fb[fb_inf->num_fb-2]);
744 fb_show_logo(fb_inf->fb[fb_inf->num_fb-2], FB_ROTATE_UR);
745 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]);
752 int rk_fb_unregister(struct rk_lcdc_device_driver *dev_drv)
755 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
757 int fb_index_base = dev_drv->fb_index_base;
758 int fb_num = dev_drv->num_layer;
762 printk(" no need to unregister null lcdc device driver!\n");
766 for(i = 0; i < fb_num; i++)
768 kfree(dev_drv->layer_par[i]);
771 for(i=fb_index_base;i<(fb_index_base+fb_num);i++)
774 unregister_framebuffer(fbi);
775 rk_release_fb_buffer(fbi);
776 framebuffer_release(fbi);
778 fb_inf->lcdc_dev_drv[dev_drv->id]= NULL;
785 #ifdef CONFIG_HAS_EARLYSUSPEND
786 struct suspend_info {
787 struct early_suspend early_suspend;
788 struct rk_fb_inf *inf;
791 static void rkfb_early_suspend(struct early_suspend *h)
793 struct suspend_info *info = container_of(h, struct suspend_info,
795 struct rk_fb_inf *inf = info->inf;
797 inf->mach_info->io_disable();
798 for(i = 0; i < inf->num_lcdc; i++)
800 atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,1);
801 inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
804 static void rkfb_early_resume(struct early_suspend *h)
806 struct suspend_info *info = container_of(h, struct suspend_info,
808 struct rk_fb_inf *inf = info->inf;
810 inf->mach_info->io_enable();
811 for(i = 0; i < inf->num_lcdc; i++)
813 inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]);
814 atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,0);
821 static struct suspend_info suspend_info = {
822 .early_suspend.suspend = rkfb_early_suspend,
823 .early_suspend.resume = rkfb_early_resume,
824 .early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
828 static int __devinit rk_fb_probe (struct platform_device *pdev)
830 struct rk_fb_inf *fb_inf = NULL;
831 struct rk29fb_info * mach_info = NULL;
834 /* Malloc rk_fb_inf and set it to pdev for drvdata */
835 fb_inf = kzalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
838 dev_err(&pdev->dev, ">>fb inf kmalloc fail!");
841 platform_set_drvdata(pdev,fb_inf);
842 mach_info = pdev->dev.platform_data;
843 fb_inf->mach_info = mach_info;
844 if(mach_info->io_init)
845 mach_info->io_init(NULL);
846 #ifdef CONFIG_HAS_EARLYSUSPEND
847 suspend_info.inf = fb_inf;
848 register_early_suspend(&suspend_info.early_suspend);
850 printk("rk fb probe ok!\n");
854 static int __devexit rk_fb_remove(struct platform_device *pdev)
856 struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
858 platform_set_drvdata(pdev, NULL);
862 static void rk_fb_shutdown(struct platform_device *pdev)
864 struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
866 platform_set_drvdata(pdev, NULL);
869 static struct platform_driver rk_fb_driver = {
870 .probe = rk_fb_probe,
871 .remove = __devexit_p(rk_fb_remove),
874 .owner = THIS_MODULE,
876 .shutdown = rk_fb_shutdown,
879 static int __init rk_fb_init(void)
881 return platform_driver_register(&rk_fb_driver);
884 static void __exit rk_fb_exit(void)
886 platform_driver_unregister(&rk_fb_driver);
889 subsys_initcall_sync(rk_fb_init);
890 module_exit(rk_fb_exit);