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>
33 #include "hdmi/rk_hdmi.h"
37 #define fbprintk(msg...) printk(msg);
39 #define fbprintk(msg...)
43 #define CHK_SUSPEND(drv) \
44 if(atomic_read(&drv->in_suspend)) { \
45 printk(">>>>>> fb is in suspend! return! \n"); \
49 #define CHK_SUSPEND(inf)
52 static struct platform_device *g_fb_pdev;
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, },
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
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 ****************************************************************************/
73 int get_fb_layer_id(struct fb_fix_screeninfo *fix)
76 if(!strcmp(fix->id,"fb1")||!strcmp(fix->id,"fb3"))
80 else if(!strcmp(fix->id,"fb0")||!strcmp(fix->id,"fb2"))
86 printk(KERN_ERR "unsupported %s",fix->id);
93 /**********************************************************************
95 name: lcdc device name ,lcdc0 , lcdc1
96 ***********************************************************************/
97 struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name)
99 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
101 for( i = 0; i < inf->num_lcdc; i++)
103 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
106 return inf->lcdc_dev_drv[i];
109 static int rk_fb_open(struct fb_info *info,int user)
111 struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
113 CHK_SUSPEND(dev_drv);
114 layer_id = get_fb_layer_id(&info->fix);
115 if(dev_drv->layer_par[layer_id]->state)
117 return 0; // if this layer aready opened ,no need to reopen
121 dev_drv->open(dev_drv,layer_id,1);
128 static int rk_fb_close(struct fb_info *info,int user)
130 struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
132 CHK_SUSPEND(dev_drv);
133 layer_id = get_fb_layer_id(&info->fix);
134 if(!dev_drv->layer_par[layer_id]->state)
140 dev_drv->open(dev_drv,layer_id,0);
145 static void fb_copy_by_ipp(struct fb_info *dst_info, struct fb_info *src_info,int offset)
147 struct rk29_ipp_req ipp_req;
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;
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;
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);
165 static void hdmi_post_work(struct work_struct *work)
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);
174 static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
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;
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);
196 par = dev_drv->layer_par[layer_id];
201 par->y_offset = (yoffset*xvir + xoffset)*4;
204 par->y_offset = (yoffset*xvir + xoffset)*3;
207 par->y_offset = (yoffset*xvir + xoffset)*2;
210 par->y_offset = yoffset*xvir + xoffset;
211 par->c_offset = par->y_offset;
214 par->y_offset = yoffset*xvir + xoffset;
215 par->c_offset = (yoffset>>1)*xvir + xoffset;
217 case YUV444 : // yuv444
218 par->y_offset = yoffset*xvir + xoffset;
219 par->c_offset = yoffset*2*xvir +(xoffset<<1);
222 printk("un supported format:0x%x\n",data_format);
226 #if defined(CONFIG_HDMI_RK30)
227 #if defined(CONFIG_DUAL_DISP_IN_KERNEL)
228 if(hdmi_get_hotplug())
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);
245 dev_drv->pan_display(dev_drv,layer_id);
248 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg)
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;
254 void __user *argp = (void __user *)arg;
255 fbprintk(">>>>>> %s : cmd:0x%x \n",__FUNCTION__,cmd);
257 CHK_SUSPEND(dev_drv);
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")))
265 if (copy_from_user(yuv_phy, argp, 8))
267 info->fix.smem_start = yuv_phy[0]; //four y
268 info->fix.mmio_start = yuv_phy[1]; //four uv
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
283 case FBIOGET_IDLEFBUff_16OR32:
284 case FBIOSET_COMPOSE_LAYER_COUNTS:
285 case FBIOGET_COMPOSE_LAYER_COUNTS:
287 dev_drv->ioctl(dev_drv,cmd,arg,0);
293 static int rk_fb_blank(int blank_mode, struct fb_info *info)
295 struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
296 struct fb_fix_screeninfo *fix = &info->fix;
298 CHK_SUSPEND(dev_drv);
299 layer_id = get_fb_layer_id(fix);
305 dev_drv->blank(dev_drv,layer_id,blank_mode);
310 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
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)) )
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);
325 if( (var->xoffset+var->xres)>var->xres_virtual ||
326 (var->yoffset+var->yres)>var->yres_virtual*2 )
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);
335 switch(var->nonstd&0x0f)
338 switch(var->bits_per_pixel)
341 var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1);
342 var->xres = (var->xres + 0x1) & (~0x1);
343 var->xoffset = (var->xoffset) & (~0x1);
346 var->bits_per_pixel = 32;
349 var->nonstd &= ~0xc0; //not support I2P in this format
352 var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3);
353 var->xres = (var->xres + 0x3) & (~0x3);
354 var->xoffset = (var->xoffset) & (~0x3);
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);
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
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
381 printk(">>>>>> fb1 var->nonstd=%d is invalid! \n", var->nonstd);
389 static int rk_fb_set_par(struct fb_info *info)
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;
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())
419 dev_drv1 = (struct rk_lcdc_device_driver * )info2->par;
424 layer_id = get_fb_layer_id(fix);
431 par = dev_drv->layer_par[layer_id];
434 par2 = dev_drv1->layer_par[layer_id];
437 if((!strcmp(fix->id,"fb0"))||(!strcmp(fix->id,"fb2"))) //four ui
439 xsize = screen->x_res;
440 ysize = screen->y_res;
442 else if((!strcmp(fix->id,"fb1"))||(!strcmp(fix->id,"fb3")))
444 xsize = (var->grayscale>>8) & 0xfff; //visiable size in panel ,for vide0
445 ysize = (var->grayscale>>20) & 0xfff;
448 /* calculate y_offset,c_offset,line_length,cblen and crlen */
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;
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;
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;
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;
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;
482 case HAL_PIXEL_FORMAT_YCrCb_444 : // yuv444
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);
490 printk("un supported format:0x%x\n",data_format);
494 switch(var->bits_per_pixel)
497 par->format = ARGB888;
498 fix->line_length = 4 * xvir;
499 par->y_offset = (yoffset*xvir + xoffset)*4;
502 par->format = RGB565;
503 fix->line_length = 2 * xvir;
504 par->y_offset = (yoffset*xvir + xoffset)*2;
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;
522 #if defined(CONFIG_HDMI_RK30)
523 #if defined(CONFIG_DUAL_DISP_IN_KERNEL)
524 if(hdmi_get_hotplug())
526 par2->xact = par->xact;
527 par2->yact = par->yact;
528 par2->format = par->format;
529 dev_drv1->set_par(dev_drv1,layer_id);
533 dev_drv->set_par(dev_drv,layer_id);
539 static inline unsigned int chan_to_field(unsigned int chan,
540 struct fb_bitfield *bf)
543 chan >>= 16 - bf->length;
544 return chan << bf->offset;
547 static int fb_setcolreg(unsigned regno,
548 unsigned red, unsigned green, unsigned blue,
549 unsigned transp, struct fb_info *info)
553 switch (info->fix.visual) {
554 case FB_VISUAL_TRUECOLOR:
555 /* true-colour, use pseudo-palette */
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);
565 return -1; /* unknown type */
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,
588 static struct fb_var_screeninfo def_var = {
589 .red = {11,5,0},//default set to rgb565,the boot logo is rgb565
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,
597 .vmode = FB_VMODE_NONINTERLACED,
600 static struct fb_fix_screeninfo def_fix = {
601 .type = FB_TYPE_PACKED_PIXELS,
606 .accel = FB_ACCEL_NONE,
607 .visual = FB_VISUAL_TRUECOLOR,
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)
619 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
620 struct fb_info *fb = inf->fb[fb_id];
623 EXPORT_SYMBOL(rk_get_fb);
625 void rk_direct_fb_show(struct fb_info * fbi)
628 rk_pan_display(&fbi->var, fbi);
630 EXPORT_SYMBOL(rk_direct_fb_show);
633 void rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id)
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;
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;
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);
675 static int rk_request_fb_buffer(struct fb_info *fbi,int fb_id)
677 struct resource *res;
678 struct resource *mem;
683 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb0 buf");
686 dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
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");
700 dev_err(&g_fb_pdev->dev, "failed to get win1 ipp memory \n");
703 fbi->fix.mmio_start = res->start;
704 fbi->fix.mmio_len = res->end - res->start + 1;
708 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb2 buf");
711 dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
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);
729 static int rk_release_fb_buffer(struct fb_info *fbi)
733 printk("no need release null fb buffer!\n");
736 if(!strcmp(fbi->fix.id,"fb1")||!strcmp(fbi->fix.id,"fb3")) //buffer for fb1 and fb3 are alloc by android
738 iounmap(fbi->screen_base);
739 release_mem_region(fbi->fix.smem_start,fbi->fix.smem_len);
743 static int init_layer_par(struct rk_lcdc_device_driver *dev_drv)
746 struct layer_par * def_par = NULL;
747 int num_par = dev_drv->num_layer;
748 for(i = 0; i < num_par; i++)
750 struct layer_par *par = NULL;
751 par = kzalloc(sizeof(struct layer_par), GFP_KERNEL);
754 printk(KERN_ERR "kzmalloc for layer_par fail!");
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;
771 static int init_lcdc_device_driver(struct rk_lcdc_device_driver *dev_drv,
772 struct rk_lcdc_device_driver *def_drv,int id)
776 printk(KERN_ERR "default lcdc device driver is null!\n");
781 printk(KERN_ERR "lcdc device driver is null!\n");
784 sprintf(dev_drv->name, "lcdc%d",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;
807 int rk_fb_register(struct rk_lcdc_device_driver *dev_drv,
808 struct rk_lcdc_device_driver *def_drv,int id)
810 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
816 printk("null lcdc device driver?");
819 for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++)
821 if(NULL==fb_inf->lcdc_dev_drv[i])
823 fb_inf->lcdc_dev_drv[i] = dev_drv;
824 fb_inf->lcdc_dev_drv[i]->id = i;
829 if(i==RK30_MAX_LCDC_SUPPORT)
831 printk("rk_fb_register lcdc out of support %d",i);
835 init_lcdc_device_driver(dev_drv, def_drv,id);
836 if(dev_drv->screen_ctr_info->set_screen_info)
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);
845 printk(KERN_WARNING "no display device on lcdc%d!?\n",dev_drv->id);
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++)
855 fbi= framebuffer_alloc(0, &g_fb_pdev->dev);
858 dev_err(&g_fb_pdev->dev,">> fb framebuffer_alloc fail!");
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);
887 printk("%s>>fb%d register_framebuffer fail!\n",__func__,fb_inf->num_fb);
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);
895 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
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]);
913 int rk_fb_unregister(struct rk_lcdc_device_driver *dev_drv)
916 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
918 int fb_index_base = dev_drv->fb_index_base;
919 int fb_num = dev_drv->num_layer;
923 printk(" no need to unregister null lcdc device driver!\n");
927 for(i = 0; i < fb_num; i++)
929 kfree(dev_drv->layer_par[i]);
932 for(i=fb_index_base;i<(fb_index_base+fb_num);i++)
935 unregister_framebuffer(fbi);
936 rk_release_fb_buffer(fbi);
937 framebuffer_release(fbi);
939 fb_inf->lcdc_dev_drv[dev_drv->id]= NULL;
946 #ifdef CONFIG_HAS_EARLYSUSPEND
947 struct suspend_info {
948 struct early_suspend early_suspend;
949 struct rk_fb_inf *inf;
952 static void rkfb_early_suspend(struct early_suspend *h)
954 struct suspend_info *info = container_of(h, struct suspend_info,
956 struct rk_fb_inf *inf = info->inf;
958 for(i = 0; i < inf->num_lcdc; i++)
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);
966 inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
969 static void rkfb_early_resume(struct early_suspend *h)
971 struct suspend_info *info = container_of(h, struct suspend_info,
973 struct rk_fb_inf *inf = info->inf;
975 for(i = 0; i < inf->num_lcdc; i++)
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);
982 inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]);
983 atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,0);
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,
997 static int __devinit rk_fb_probe (struct platform_device *pdev)
999 struct rk_fb_inf *fb_inf = NULL;
1000 struct rk29fb_info * mach_info = NULL;
1003 /* Malloc rk_fb_inf and set it to pdev for drvdata */
1004 fb_inf = kzalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
1007 dev_err(&pdev->dev, ">>fb inf kmalloc fail!");
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);
1018 #ifdef CONFIG_HAS_EARLYSUSPEND
1019 suspend_info.inf = fb_inf;
1020 register_early_suspend(&suspend_info.early_suspend);
1022 printk("rk fb probe ok!\n");
1026 static int __devexit rk_fb_remove(struct platform_device *pdev)
1028 struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
1030 platform_set_drvdata(pdev, NULL);
1034 static void rk_fb_shutdown(struct platform_device *pdev)
1036 struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
1038 platform_set_drvdata(pdev, NULL);
1041 static struct platform_driver rk_fb_driver = {
1042 .probe = rk_fb_probe,
1043 .remove = __devexit_p(rk_fb_remove),
1046 .owner = THIS_MODULE,
1048 .shutdown = rk_fb_shutdown,
1051 static int __init rk_fb_init(void)
1053 return platform_driver_register(&rk_fb_driver);
1056 static void __exit rk_fb_exit(void)
1058 platform_driver_unregister(&rk_fb_driver);
1061 subsys_initcall_sync(rk_fb_init);
1062 module_exit(rk_fb_exit);