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>
25 #include <linux/kthread.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>
34 #include "hdmi/rk_hdmi.h"
35 #include <linux/linux_logo.h>
37 void rk29_backlight_set(bool on);
38 bool rk29_get_backlight_status(void);
40 #ifdef CONFIG_FB_MIRRORING
43 int (*video_data_to_mirroring)(struct fb_info *info,u32 yuv_phy[2]) = NULL;
44 EXPORT_SYMBOL(video_data_to_mirroring);
47 static struct platform_device *g_fb_pdev;
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, },
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
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 ****************************************************************************/
70 /**********************************************************************
72 name: lcdc device name ,lcdc0 , lcdc1
73 ***********************************************************************/
74 struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name)
76 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
78 for( i = 0; i < inf->num_lcdc; i++)
80 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
83 return inf->lcdc_dev_drv[i];
86 static int rk_fb_open(struct fb_info *info,int user)
88 struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
91 layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
92 if(dev_drv->layer_par[layer_id]->state)
94 return 0; // if this layer aready opened ,no need to reopen
98 dev_drv->open(dev_drv,layer_id,1);
105 static int rk_fb_close(struct fb_info *info,int user)
107 /*struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
109 CHK_SUSPEND(dev_drv);
110 layer_id = get_fb_layer_id(&info->fix);
111 if(!dev_drv->layer_par[layer_id]->state)
117 dev_drv->open(dev_drv,layer_id,0);
122 static void fb_copy_by_ipp(struct fb_info *dst_info, struct fb_info *src_info,int offset)
124 struct rk29_ipp_req ipp_req;
126 uint32_t rotation = 0;
127 #if defined(CONFIG_FB_ROTATE)
128 int orientation = orientation = 270 - CONFIG_ROTATE_ORIENTATION;
132 rotation = IPP_ROT_0;
135 rotation = IPP_ROT_90;
138 rotation = IPP_ROT_180;
141 rotation = IPP_ROT_270;
144 rotation = IPP_ROT_270;
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 = rotation;
162 ipp_blit_sync(&ipp_req);
169 static void hdmi_post_work(struct work_struct *work)
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));
191 static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
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;
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;
206 layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
213 par = dev_drv->layer_par[layer_id];
220 par->y_offset = (yoffset*xvir + xoffset)*4;
223 par->y_offset = (yoffset*xvir + xoffset)*3;
226 par->y_offset = (yoffset*xvir + xoffset)*2;
229 par->y_offset = yoffset*xvir + xoffset;
230 par->c_offset = par->y_offset;
233 par->y_offset = yoffset*xvir + xoffset;
234 par->c_offset = (yoffset>>1)*xvir + xoffset;
236 case YUV444 : // yuv444
237 par->y_offset = yoffset*xvir + xoffset;
238 par->c_offset = yoffset*2*xvir +(xoffset<<1);
241 printk("un supported format:0x%x\n",data_format);
245 #if defined(CONFIG_RK_HDMI)
246 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
247 if(hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
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);
260 dev_drv1->pan_display(dev_drv1,layer_id);
261 //queue_delayed_work(inf->workqueue, &inf->delay_work,0);
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);
273 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg)
275 struct fb_fix_screeninfo *fix = &info->fix;
276 struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
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;
286 case FBIOPUT_FBPHYADD:
287 return info->fix.smem_start;
289 case RK_FBIOSET_YUV_ADDR: //when in video mode, buff alloc by android
290 //if((!strcmp(fix->id,"fb1"))||(!strcmp(fix->id,"fb3")))
292 if (copy_from_user(yuv_phy, argp, 8))
294 info->fix.smem_start = yuv_phy[0]; //four y
295 info->fix.mmio_start = yuv_phy[1]; //four uv
298 case RK_FBIOSET_ENABLE:
299 if (copy_from_user(&enable, argp, sizeof(enable)))
301 dev_drv->open(dev_drv,layer_id,enable);
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)))
308 case RK_FBIOSET_OVERLAY_STATE:
309 if (copy_from_user(&ovl, argp, sizeof(ovl)))
311 dev_drv->ovl_mgr(dev_drv,ovl,1);
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)))
318 case RK_FBIOPUT_NUM_BUFFERS:
319 if (copy_from_user(&num_buf, argp, sizeof(num_buf)))
321 dev_drv->num_buf = num_buf;
322 printk("rk fb use %d buffers\n",num_buf);
324 case RK_FBIOSET_VSYNC_ENABLE:
325 if (copy_from_user(&enable, argp, sizeof(enable)))
327 dev_drv->vsync_info.active = enable;
330 dev_drv->ioctl(dev_drv,cmd,arg,layer_id);
336 static int rk_fb_blank(int blank_mode, struct fb_info *info)
338 struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
339 struct fb_fix_screeninfo *fix = &info->fix;
342 layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
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");
355 dev_drv->blank(dev_drv,layer_id,blank_mode);
360 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
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)) )
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);
374 if( ((var->xoffset+var->xres) > var->xres_virtual) ||
375 ((var->yoffset+var->yres) > (var->yres_virtual)) )
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);
387 static int rk_fb_set_par(struct fb_info *info)
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;
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;
410 #if defined(CONFIG_RK_HDMI)
411 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
412 if(hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
416 info2 = inf->fb[inf->num_fb>>1];
417 dev_drv1 = (struct rk_lcdc_device_driver * )info2->par;
422 layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
429 par = dev_drv->layer_par[layer_id];
432 par2 = dev_drv1->layer_par[layer_id];
436 if(var->grayscale>>8) //if the application has specific the horizontal and vertical display size
438 xsize = (var->grayscale>>8) & 0xfff; //visiable size in panel ,for vide0
439 ysize = (var->grayscale>>20) & 0xfff;
441 else //ohterwise full screen display
443 xsize = screen->x_res;
444 ysize = screen->y_res;
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;
457 xsize = dev_drv->screen1->xsize;
458 ysize = dev_drv->screen1->ysize;
459 xpos = dev_drv->screen1->xpos;
460 ypos = dev_drv->screen1->ypos;
463 /* calculate y_offset,c_offset,line_length,cblen and crlen */
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;
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;
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;
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;
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;
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;
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;
506 case HAL_PIXEL_FORMAT_YCrCb_444 : // yuv444
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);
514 printk("%s:un supported format:0x%x\n",__func__,data_format);
518 switch(var->bits_per_pixel)
521 par->format = ARGB888;
522 fix->line_length = 4 * xvir;
523 par->y_offset = (yoffset*xvir + xoffset)*4;
526 par->format = RGB565;
527 fix->line_length = 2 * xvir;
528 par->y_offset = (yoffset*xvir + xoffset)*2;
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;
546 #if defined(CONFIG_RK_HDMI)
547 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
548 if(hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
552 par2->xact = par->xact;
553 par2->yact = par->yact;
554 par2->format = par->format;
555 par2->xvir = par->xvir;
556 info2->var.nonstd &= 0xffffff00;
557 info2->var.nonstd |= data_format;
558 dev_drv1->set_par(dev_drv1,layer_id);
563 dev_drv->set_par(dev_drv,layer_id);
569 static inline unsigned int chan_to_field(unsigned int chan,
570 struct fb_bitfield *bf)
573 chan >>= 16 - bf->length;
574 return chan << bf->offset;
577 static int fb_setcolreg(unsigned regno,
578 unsigned red, unsigned green, unsigned blue,
579 unsigned transp, struct fb_info *info)
583 switch (info->fix.visual) {
584 case FB_VISUAL_TRUECOLOR:
585 /* true-colour, use pseudo-palette */
587 u32 *pal = info->pseudo_palette;
588 val = chan_to_field(red, &info->var.red);
589 val |= chan_to_field(green, &info->var.green);
590 val |= chan_to_field(blue, &info->var.blue);
595 return -1; /* unknown type */
601 static struct fb_ops fb_ops = {
602 .owner = THIS_MODULE,
603 .fb_open = rk_fb_open,
604 .fb_release = rk_fb_close,
605 .fb_check_var = rk_fb_check_var,
606 .fb_set_par = rk_fb_set_par,
607 .fb_blank = rk_fb_blank,
608 .fb_ioctl = rk_fb_ioctl,
609 .fb_pan_display = rk_pan_display,
610 .fb_setcolreg = fb_setcolreg,
611 .fb_fillrect = cfb_fillrect,
612 .fb_copyarea = cfb_copyarea,
613 .fb_imageblit = cfb_imageblit,
618 static struct fb_var_screeninfo def_var = {
619 .red = {11,5,0},//default set to rgb565,the boot logo is rgb565
623 #ifdef CONFIG_LOGO_LINUX_BMP
624 .nonstd = HAL_PIXEL_FORMAT_RGBA_8888,
626 .nonstd = HAL_PIXEL_FORMAT_RGB_565, //(ypos<<20+xpos<<8+format) format
628 .grayscale = 0, //(ysize<<20+xsize<<8)
629 .activate = FB_ACTIVATE_NOW,
631 .vmode = FB_VMODE_NONINTERLACED,
634 static struct fb_fix_screeninfo def_fix = {
635 .type = FB_TYPE_PACKED_PIXELS,
640 .accel = FB_ACCEL_NONE,
641 .visual = FB_VISUAL_TRUECOLOR,
646 static int rk_fb_wait_for_vsync_thread(void *data)
648 struct rk_lcdc_device_driver *dev_drv = data;
649 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
650 struct fb_info *fbi = inf->fb[0];
652 while (!kthread_should_stop()) {
653 ktime_t timestamp = dev_drv->vsync_info.timestamp;
654 int ret = wait_event_interruptible(dev_drv->vsync_info.wait,
655 !ktime_equal(timestamp, dev_drv->vsync_info.timestamp) &&
656 dev_drv->vsync_info.active);
659 sysfs_notify(&fbi->dev->kobj, NULL, "vsync");
666 static ssize_t rk_fb_vsync_show(struct device *dev,
667 struct device_attribute *attr, char *buf)
669 struct fb_info *fbi = dev_get_drvdata(dev);
670 struct rk_lcdc_device_driver * dev_drv =
671 (struct rk_lcdc_device_driver * )fbi->par;
672 return scnprintf(buf, PAGE_SIZE, "%llu\n",
673 ktime_to_ns(dev_drv->vsync_info.timestamp));
676 static DEVICE_ATTR(vsync, S_IRUGO, rk_fb_vsync_show, NULL);
679 /*****************************************************************
680 this two function is for other module that in the kernel which
681 need show image directly through fb
682 fb_id:we have 4 fb here,default we use fb0 for ui display
683 *******************************************************************/
684 struct fb_info * rk_get_fb(int fb_id)
686 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
687 struct fb_info *fb = inf->fb[fb_id];
690 EXPORT_SYMBOL(rk_get_fb);
692 void rk_direct_fb_show(struct fb_info * fbi)
695 rk_pan_display(&fbi->var, fbi);
697 EXPORT_SYMBOL(rk_direct_fb_show);
701 /******************************************
702 function:this function will be called by hdmi,when
704 screen: the screen attached to hdmi
705 enable: 1,hdmi plug in,0,hdmi plug out
706 lcdc_id: the lcdc id the hdmi attached ,0 or 1
707 ******************************************/
708 int rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id)
710 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
711 struct fb_info *info = NULL;
712 struct fb_info *pmy_info = NULL;
713 struct rk_lcdc_device_driver * dev_drv = NULL;
714 struct fb_var_screeninfo *pmy_var = NULL; //var for primary screen
715 struct fb_var_screeninfo *hdmi_var = NULL;
716 struct fb_fix_screeninfo *pmy_fix = NULL;
717 struct fb_fix_screeninfo *hdmi_fix = NULL;
723 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) || defined(CONFIG_NO_DUAL_DISP)
724 rk29_backlight_set(0);
727 sprintf(name, "lcdc%d",lcdc_id);
728 for(i = 0; i < inf->num_lcdc; i++) //find the driver for the extend display device
730 if(inf->lcdc_dev_drv[i]->screen_ctr_info->prop == EXTEND)
732 dev_drv = inf->lcdc_dev_drv[i];
733 printk("hdmi connect to lcdc%d\n",dev_drv->id);
738 if(i == inf->num_lcdc)
740 printk(KERN_ERR "%s driver not found!",name);
746 if(inf->num_lcdc == 1)
750 else if(inf->num_lcdc == 2)
752 info = inf->fb[dev_drv->num_layer]; //the main fb of lcdc1
755 if(dev_drv->screen1) //device like rk2928 ,have only one lcdc but two outputs
759 memcpy(dev_drv->screen1,screen,sizeof(rk_screen ));
760 dev_drv->screen1->lcdc_id = 0; //connect screen1 to output interface 0
761 dev_drv->screen1->screen_id = 1;
762 dev_drv->screen0->lcdc_id = 1; //connect screen0 to output interface 1
763 dev_drv->cur_screen = dev_drv->screen1;
764 if(dev_drv->screen0->sscreen_get)
766 dev_drv->screen0->sscreen_get(dev_drv->screen0,
767 dev_drv->cur_screen->hdmi_resolution);
769 if(dev_drv->screen0->sscreen_set)
771 dev_drv->screen0->sscreen_set(dev_drv->screen0,enable);
777 dev_drv->screen1->lcdc_id = 1; //connect screen1 to output interface 1
778 dev_drv->screen0->lcdc_id = 0; //connect screen0 to output interface 0
779 dev_drv->cur_screen = dev_drv->screen0;
780 dev_drv->screen_ctr_info->set_screen_info(dev_drv->cur_screen,
781 dev_drv->screen_ctr_info->lcd_info);
789 memcpy(dev_drv->cur_screen,screen,sizeof(rk_screen ));
794 layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
796 if(!enable && !dev_drv->screen1) //only double lcdc device need to close
798 if(dev_drv->layer_par[layer_id]->state)
800 dev_drv->open(dev_drv,layer_id,enable); //disable the layer which attached to this fb
805 hdmi_var = &info->var;
806 hdmi_fix = &info->fix;
807 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
808 if(likely(inf->num_lcdc == 2))
810 pmy_var = &inf->fb[0]->var;
811 pmy_fix = &inf->fb[0]->fix;
812 hdmi_var->xres = pmy_var->xres;
813 hdmi_var->yres = pmy_var->yres;
814 hdmi_var->xres_virtual = pmy_var->xres_virtual;
815 hdmi_var->yres_virtual = pmy_var->yres_virtual;
816 hdmi_var->nonstd &= 0xffffff00;
817 hdmi_var->nonstd |= (pmy_var->nonstd & 0xff); //use the same format as primary screen
821 printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!",__func__);
824 hdmi_var->grayscale &= 0xff;
825 hdmi_var->grayscale |= (dev_drv->cur_screen->x_res<<8) + (dev_drv->cur_screen->y_res<<20);
827 if(dev_drv->screen1) //device like rk2928,whic have one lcdc but two outputs
829 // info->var.nonstd &= 0xff;
830 // info->var.nonstd |= (dev_drv->cur_screen->xpos<<8) + (dev_drv->cur_screen->ypos<<20);
831 // info->var.grayscale &= 0xff;
832 // info->var.grayscale |= (dev_drv->cur_screen->x_res<<8) + (dev_drv->cur_screen->y_res<<20);
833 dev_drv->screen1->xsize = dev_drv->cur_screen->x_res;
834 dev_drv->screen1->ysize = dev_drv->cur_screen->y_res;
835 dev_drv->screen1->xpos = 0;
836 dev_drv->screen1->ypos = 0;
838 ret = info->fbops->fb_open(info,1);
839 dev_drv->load_screen(dev_drv,1);
840 ret = info->fbops->fb_set_par(info);
841 if(dev_drv->lcdc_hdmi_process)
842 dev_drv->lcdc_hdmi_process(dev_drv,enable);
844 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
845 if(likely(inf->num_lcdc == 2))
847 pmy_info = inf->fb[0];
848 pmy_info->fbops->fb_pan_display(pmy_var,pmy_info);
852 printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!",__func__);
854 #elif defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
855 info->fbops->fb_pan_display(hdmi_var,info);
858 #if defined(CONFIG_NO_DUAL_DISP) //close backlight for device whic do not support dual display
860 rk29_backlight_set(1);
861 #elif defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) //close backlight for device whic do not support dual display
862 rk29_backlight_set(1);
871 /******************************************
872 function:this function current only called by hdmi for
874 scale_x: scale rate of x resolution
875 scale_y: scale rate of y resolution
876 lcdc_id: the lcdc id the hdmi attached ,0 or 1
877 ******************************************/
879 int rk_fb_disp_scale(u8 scale_x, u8 scale_y,u8 lcdc_id)
881 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
882 struct fb_info *info = NULL;
883 struct fb_var_screeninfo *var = NULL;
884 struct rk_lcdc_device_driver * dev_drv = NULL;
885 u16 screen_x,screen_y;
891 sprintf(name, "lcdc%d",lcdc_id);
892 for(i = 0; i < inf->num_lcdc; i++)
894 if(inf->lcdc_dev_drv[i]->screen_ctr_info->prop == EXTEND)
896 dev_drv = inf->lcdc_dev_drv[i];
901 if(i == inf->num_lcdc)
903 printk(KERN_ERR "%s driver not found!",name);
908 if(inf->num_lcdc == 1)
912 else if(inf->num_lcdc == 2)
914 info = inf->fb[dev_drv->num_layer];
918 screen_x = dev_drv->cur_screen->x_res;
919 screen_y = dev_drv->cur_screen->y_res;
921 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)||defined(CONFIG_NO_DUAL_DISP)
922 if(dev_drv->cur_screen->screen_id == 1){
923 dev_drv->cur_screen->xpos = (screen_x-screen_x*scale_x/100)>>1;
924 dev_drv->cur_screen->ypos = (screen_y-screen_y*scale_y/100)>>1;
925 dev_drv->cur_screen->xsize = screen_x*scale_x/100;
926 dev_drv->cur_screen->ysize = screen_y*scale_y/100;
930 xpos = (screen_x-screen_x*scale_x/100)>>1;
931 ypos = (screen_y-screen_y*scale_y/100)>>1;
932 xsize = screen_x*scale_x/100;
933 ysize = screen_y*scale_y/100;
935 var->nonstd |= (xpos<<8) + (ypos<<20);
936 var->grayscale &= 0xff;
937 var->grayscale |= (xsize<<8) + (ysize<<20);
940 info->fbops->fb_set_par(info);
946 static int rk_request_fb_buffer(struct fb_info *fbi,int fb_id)
948 struct resource *res;
949 struct resource *mem;
951 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
952 if (!strcmp(fbi->fix.id,"fb0"))
954 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb0 buf");
957 dev_err(&g_fb_pdev->dev, "failed to get memory for fb0 \n");
960 fbi->fix.smem_start = res->start;
961 fbi->fix.smem_len = res->end - res->start + 1;
962 mem = request_mem_region(res->start, resource_size(res), g_fb_pdev->name);
963 fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
964 memset(fbi->screen_base, 0, fbi->fix.smem_len);
965 printk("fb%d:phy:%lx>>vir:%p>>len:0x%x\n",fb_id,
966 fbi->fix.smem_start,fbi->screen_base,fbi->fix.smem_len);
970 #if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
971 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb2 buf");
974 dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
977 fbi->fix.smem_start = res->start;
978 fbi->fix.smem_len = res->end - res->start + 1;
979 mem = request_mem_region(res->start, resource_size(res), g_fb_pdev->name);
980 fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
981 memset(fbi->screen_base, 0, fbi->fix.smem_len);
982 #else //three buffer no need to copy
983 fbi->fix.smem_start = fb_inf->fb[0]->fix.smem_start;
984 fbi->fix.smem_len = fb_inf->fb[0]->fix.smem_len;
985 fbi->screen_base = fb_inf->fb[0]->screen_base;
987 printk("fb%d:phy:%lx>>vir:%p>>len:0x%x\n",fb_id,
988 fbi->fix.smem_start,fbi->screen_base,fbi->fix.smem_len);
993 static int rk_release_fb_buffer(struct fb_info *fbi)
997 printk("no need release null fb buffer!\n");
1000 if(!strcmp(fbi->fix.id,"fb1")||!strcmp(fbi->fix.id,"fb3")) //buffer for fb1 and fb3 are alloc by android
1002 iounmap(fbi->screen_base);
1003 release_mem_region(fbi->fix.smem_start,fbi->fix.smem_len);
1007 static int init_layer_par(struct rk_lcdc_device_driver *dev_drv)
1010 struct layer_par * def_par = NULL;
1011 int num_par = dev_drv->num_layer;
1012 for(i = 0; i < num_par; i++)
1014 struct layer_par *par = NULL;
1015 par = kzalloc(sizeof(struct layer_par), GFP_KERNEL);
1018 printk(KERN_ERR "kzmalloc for layer_par fail!");
1022 def_par = &dev_drv->def_layer_par[i];
1023 strcpy(par->name,def_par->name);
1024 par->id = def_par->id;
1025 par->support_3d = def_par->support_3d;
1026 dev_drv->layer_par[i] = par;
1035 static int init_lcdc_device_driver(struct rk_lcdc_device_driver *dev_drv,
1036 struct rk_lcdc_device_driver *def_drv,int id)
1040 printk(KERN_ERR "default lcdc device driver is null!\n");
1045 printk(KERN_ERR "lcdc device driver is null!\n");
1048 sprintf(dev_drv->name, "lcdc%d",id);
1050 dev_drv->open = def_drv->open;
1051 dev_drv->init_lcdc = def_drv->init_lcdc;
1052 dev_drv->ioctl = def_drv->ioctl;
1053 dev_drv->blank = def_drv->blank;
1054 dev_drv->set_par = def_drv->set_par;
1055 dev_drv->pan_display = def_drv->pan_display;
1056 dev_drv->suspend = def_drv->suspend;
1057 dev_drv->resume = def_drv->resume;
1058 dev_drv->load_screen = def_drv->load_screen;
1059 dev_drv->def_layer_par = def_drv->def_layer_par;
1060 dev_drv->num_layer = def_drv->num_layer;
1061 dev_drv->get_layer_state= def_drv->get_layer_state;
1062 dev_drv->get_disp_info = def_drv->get_disp_info;
1063 dev_drv->ovl_mgr = def_drv->ovl_mgr;
1064 dev_drv->fps_mgr = def_drv->fps_mgr;
1065 if(def_drv->fb_get_layer)
1066 dev_drv->fb_get_layer = def_drv->fb_get_layer;
1067 if(def_drv->fb_layer_remap)
1068 dev_drv->fb_layer_remap = def_drv->fb_layer_remap;
1069 if(def_drv->set_dsp_lut)
1070 dev_drv->set_dsp_lut = def_drv->set_dsp_lut;
1071 if(def_drv->read_dsp_lut)
1072 dev_drv->read_dsp_lut = def_drv->read_dsp_lut;
1073 if(def_drv->lcdc_hdmi_process)
1074 dev_drv->lcdc_hdmi_process = def_drv->lcdc_hdmi_process;
1075 init_layer_par(dev_drv);
1076 init_completion(&dev_drv->frame_done);
1077 spin_lock_init(&dev_drv->cpl_lock);
1078 mutex_init(&dev_drv->fb_win_id_mutex);
1079 dev_drv->fb_layer_remap(dev_drv,FB_DEFAULT_ORDER); //102
1080 dev_drv->first_frame = 1;
1085 #ifdef CONFIG_LOGO_LINUX_BMP
1086 static struct linux_logo *bmp_logo;
1087 static int fb_prepare_bmp_logo(struct fb_info *info, int rotate)
1089 bmp_logo = fb_find_logo(24);
1090 if (bmp_logo == NULL) {
1091 printk("%s error\n", __func__);
1097 static void fb_show_bmp_logo(struct fb_info *info, int rotate)
1099 unsigned char *src=bmp_logo->data;
1100 unsigned char *dst=info->screen_base;
1102 unsigned int Needwidth=(*(src-24)<<8)|(*(src-23));
1103 unsigned int Needheight=(*(src-22)<<8)|(*(src-21));
1105 for(i=0;i<Needheight;i++)
1106 memcpy(dst+info->var.xres*i*4, src+bmp_logo->width*i*4, Needwidth*4);
1111 int rk_fb_register(struct rk_lcdc_device_driver *dev_drv,
1112 struct rk_lcdc_device_driver *def_drv,int id)
1114 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
1115 struct fb_info *fbi;
1120 printk("null lcdc device driver?");
1123 for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++)
1125 if(NULL==fb_inf->lcdc_dev_drv[i])
1127 fb_inf->lcdc_dev_drv[i] = dev_drv;
1128 fb_inf->lcdc_dev_drv[i]->id = id;
1133 if(i==RK30_MAX_LCDC_SUPPORT)
1135 printk("rk_fb_register lcdc out of support %d",i);
1139 init_lcdc_device_driver(dev_drv, def_drv,id);
1141 dev_drv->init_lcdc(dev_drv);
1142 /************fb set,one layer one fb ***********/
1143 dev_drv->fb_index_base = fb_inf->num_fb;
1144 for(i=0;i<dev_drv->num_layer;i++)
1146 fbi= framebuffer_alloc(0, &g_fb_pdev->dev);
1149 dev_err(&g_fb_pdev->dev,">> fb framebuffer_alloc fail!");
1156 sprintf(fbi->fix.id,"fb%d",fb_inf->num_fb);
1157 fbi->var.xres = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->x_res;
1158 fbi->var.yres = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->y_res;
1159 fbi->var.grayscale |= (fbi->var.xres<<8) + (fbi->var.yres<<20);
1160 #ifdef CONFIG_LOGO_LINUX_BMP
1161 fbi->var.bits_per_pixel = 32;
1163 fbi->var.bits_per_pixel = 16;
1165 fbi->fix.line_length = (fbi->var.xres)*(fbi->var.bits_per_pixel>>3);
1166 fbi->var.xres_virtual = fbi->var.xres;
1167 fbi->var.yres_virtual = fbi->var.yres;
1168 fbi->var.width = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->width;
1169 fbi->var.height = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->height;
1170 fbi->var.pixclock = fb_inf->lcdc_dev_drv[lcdc_id]->pixclock;
1171 fbi->var.left_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->left_margin;
1172 fbi->var.right_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->right_margin;
1173 fbi->var.upper_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->upper_margin;
1174 fbi->var.lower_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->lower_margin;
1175 fbi->var.vsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->vsync_len;
1176 fbi->var.hsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->hsync_len;
1177 fbi->fbops = &fb_ops;
1178 fbi->flags = FBINFO_FLAG_DEFAULT;
1179 fbi->pseudo_palette = fb_inf->lcdc_dev_drv[lcdc_id]->layer_par[i]->pseudo_pal;
1180 if (i == 0) //only alloc memory for main fb
1182 rk_request_fb_buffer(fbi,fb_inf->num_fb);
1184 ret = register_framebuffer(fbi);
1187 printk("%s>>fb%d register_framebuffer fail!\n",__func__,fb_inf->num_fb);
1190 rkfb_create_sysfs(fbi);
1194 init_waitqueue_head(&dev_drv->vsync_info.wait);
1195 ret = device_create_file(fbi->dev,&dev_attr_vsync);
1198 dev_err(fbi->dev, "failed to create vsync file\n");
1200 dev_drv->vsync_info.thread = kthread_run(rk_fb_wait_for_vsync_thread,
1201 dev_drv, "fb-vsync");
1204 if (dev_drv->vsync_info.thread == ERR_PTR(-ENOMEM))
1206 dev_err(fbi->dev, "failed to run vsync thread\n");
1207 dev_drv->vsync_info.thread = NULL;
1209 dev_drv->vsync_info.active = 1;
1211 fb_inf->fb[fb_inf->num_fb] = fbi;
1212 printk("%s>>>>>%s\n",__func__,fb_inf->fb[fb_inf->num_fb]->fix.id);
1215 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
1216 if(dev_drv->screen_ctr_info->prop == PRMRY) //show logo for primary display device
1218 fb_inf->fb[0]->fbops->fb_open(fb_inf->fb[0],1);
1219 fb_inf->fb[0]->fbops->fb_set_par(fb_inf->fb[0]);
1221 #if defined(CONFIG_LOGO_LINUX_BMP)
1222 if(fb_prepare_bmp_logo(fb_inf->fb[0], FB_ROTATE_UR)) {
1223 /* Start display and show logo on boot */
1224 fb_set_cmap(&fb_inf->fb[0]->cmap, fb_inf->fb[0]);
1225 fb_show_bmp_logo(fb_inf->fb[0], FB_ROTATE_UR);
1226 fb_inf->fb[0]->fbops->fb_pan_display(&(fb_inf->fb[0]->var), fb_inf->fb[0]);
1229 if(fb_prepare_logo(fb_inf->fb[0], FB_ROTATE_UR)) {
1230 /* Start display and show logo on boot */
1231 fb_set_cmap(&fb_inf->fb[0]->cmap, fb_inf->fb[0]);
1232 fb_show_logo(fb_inf->fb[0], FB_ROTATE_UR);
1233 fb_inf->fb[0]->fbops->fb_pan_display(&(fb_inf->fb[0]->var), fb_inf->fb[0]);
1243 int rk_fb_unregister(struct rk_lcdc_device_driver *dev_drv)
1246 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
1247 struct fb_info *fbi;
1248 int fb_index_base = dev_drv->fb_index_base;
1249 int fb_num = dev_drv->num_layer;
1253 printk(" no need to unregister null lcdc device driver!\n");
1257 for(i = 0; i < fb_num; i++)
1259 kfree(dev_drv->layer_par[i]);
1262 for(i=fb_index_base;i<(fb_index_base+fb_num);i++)
1264 fbi = fb_inf->fb[i];
1265 unregister_framebuffer(fbi);
1266 //rk_release_fb_buffer(fbi);
1267 framebuffer_release(fbi);
1269 fb_inf->lcdc_dev_drv[dev_drv->id]= NULL;
1277 #ifdef CONFIG_HAS_EARLYSUSPEND
1278 struct suspend_info {
1279 struct early_suspend early_suspend;
1280 struct rk_fb_inf *inf;
1283 static void rkfb_early_suspend(struct early_suspend *h)
1285 struct suspend_info *info = container_of(h, struct suspend_info,
1287 struct rk_fb_inf *inf = info->inf;
1289 for(i = 0; i < inf->num_lcdc; i++)
1291 if (!inf->lcdc_dev_drv[i])
1294 inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
1297 static void rkfb_early_resume(struct early_suspend *h)
1299 struct suspend_info *info = container_of(h, struct suspend_info,
1301 struct rk_fb_inf *inf = info->inf;
1303 for(i = 0; i < inf->num_lcdc; i++)
1305 if (!inf->lcdc_dev_drv[i])
1308 inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]); // data out
1315 static struct suspend_info suspend_info = {
1316 .early_suspend.suspend = rkfb_early_suspend,
1317 .early_suspend.resume = rkfb_early_resume,
1318 .early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
1322 static int __devinit rk_fb_probe (struct platform_device *pdev)
1324 struct rk_fb_inf *fb_inf = NULL;
1327 /* Malloc rk_fb_inf and set it to pdev for drvdata */
1328 fb_inf = kzalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
1331 dev_err(&pdev->dev, ">>fb inf kmalloc fail!");
1334 platform_set_drvdata(pdev,fb_inf);
1336 #ifdef CONFIG_HAS_EARLYSUSPEND
1337 suspend_info.inf = fb_inf;
1338 register_early_suspend(&suspend_info.early_suspend);
1340 printk("rk fb probe ok!\n");
1344 static int __devexit rk_fb_remove(struct platform_device *pdev)
1346 struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
1348 platform_set_drvdata(pdev, NULL);
1352 static void rk_fb_shutdown(struct platform_device *pdev)
1354 struct rk_fb_inf *inf = platform_get_drvdata(pdev);
1356 for(i = 0; i < inf->num_lcdc; i++)
1358 if (!inf->lcdc_dev_drv[i])
1361 if(inf->lcdc_dev_drv[i]->vsync_info.thread)
1362 kthread_stop(inf->lcdc_dev_drv[i]->vsync_info.thread);
1365 // platform_set_drvdata(pdev, NULL);
1366 #ifdef CONFIG_HAS_EARLYSUSPEND
1367 unregister_early_suspend(&suspend_info.early_suspend);
1371 static struct platform_driver rk_fb_driver = {
1372 .probe = rk_fb_probe,
1373 .remove = __devexit_p(rk_fb_remove),
1376 .owner = THIS_MODULE,
1378 .shutdown = rk_fb_shutdown,
1381 static int __init rk_fb_init(void)
1383 return platform_driver_register(&rk_fb_driver);
1386 static void __exit rk_fb_exit(void)
1388 platform_driver_unregister(&rk_fb_driver);
1391 subsys_initcall_sync(rk_fb_init);
1392 module_exit(rk_fb_exit);