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 info2->var.nonstd &= 0xffffff00;
556 info2->var.nonstd |= data_format;
557 dev_drv1->set_par(dev_drv1,layer_id);
562 dev_drv->set_par(dev_drv,layer_id);
568 static inline unsigned int chan_to_field(unsigned int chan,
569 struct fb_bitfield *bf)
572 chan >>= 16 - bf->length;
573 return chan << bf->offset;
576 static int fb_setcolreg(unsigned regno,
577 unsigned red, unsigned green, unsigned blue,
578 unsigned transp, struct fb_info *info)
582 switch (info->fix.visual) {
583 case FB_VISUAL_TRUECOLOR:
584 /* true-colour, use pseudo-palette */
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);
594 return -1; /* unknown type */
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,
617 static struct fb_var_screeninfo def_var = {
618 .red = {11,5,0},//default set to rgb565,the boot logo is rgb565
622 #ifdef CONFIG_LOGO_LINUX_BMP
623 .nonstd = HAL_PIXEL_FORMAT_RGBA_8888,
625 .nonstd = HAL_PIXEL_FORMAT_RGB_565, //(ypos<<20+xpos<<8+format) format
627 .grayscale = 0, //(ysize<<20+xsize<<8)
628 .activate = FB_ACTIVATE_NOW,
630 .vmode = FB_VMODE_NONINTERLACED,
633 static struct fb_fix_screeninfo def_fix = {
634 .type = FB_TYPE_PACKED_PIXELS,
639 .accel = FB_ACCEL_NONE,
640 .visual = FB_VISUAL_TRUECOLOR,
645 static int rk_fb_wait_for_vsync_thread(void *data)
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];
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);
658 sysfs_notify(&fbi->dev->kobj, NULL, "vsync");
665 static ssize_t rk_fb_vsync_show(struct device *dev,
666 struct device_attribute *attr, char *buf)
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));
675 static DEVICE_ATTR(vsync, S_IRUGO, rk_fb_vsync_show, NULL);
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)
685 struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev);
686 struct fb_info *fb = inf->fb[fb_id];
689 EXPORT_SYMBOL(rk_get_fb);
691 void rk_direct_fb_show(struct fb_info * fbi)
694 rk_pan_display(&fbi->var, fbi);
696 EXPORT_SYMBOL(rk_direct_fb_show);
700 /******************************************
701 function:this function will be called by hdmi,when
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)
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;
722 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) || defined(CONFIG_NO_DUAL_DISP)
723 rk29_backlight_set(0);
726 sprintf(name, "lcdc%d",lcdc_id);
727 for(i = 0; i < inf->num_lcdc; i++) //find the driver the display device connected to
729 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
731 dev_drv = inf->lcdc_dev_drv[i];
736 if(i == inf->num_lcdc)
738 printk(KERN_ERR "%s driver not found!",name);
744 if((lcdc_id == 0) || (inf->num_lcdc == 1))
748 else if((lcdc_id == 1)&&(inf->num_lcdc == 2))
750 info = inf->fb[dev_drv->num_layer]; //the main fb of lcdc1
753 if(dev_drv->screen1) //device like rk2928 ,have only one lcdc but two outputs
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)
764 dev_drv->screen0->sscreen_get(dev_drv->screen0,
765 dev_drv->cur_screen->hdmi_resolution);
767 if(dev_drv->screen0->sscreen_set)
769 dev_drv->screen0->sscreen_set(dev_drv->screen0,enable);
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);
787 memcpy(dev_drv->cur_screen,screen,sizeof(rk_screen ));
792 layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
794 if(!enable && !dev_drv->screen1) //only double lcdc device need to close
796 if(dev_drv->layer_par[layer_id]->state)
798 dev_drv->open(dev_drv,layer_id,enable); //disable the layer which attached to this fb
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))
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
819 printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!",__func__);
822 hdmi_var->grayscale &= 0xff;
823 hdmi_var->grayscale |= (dev_drv->cur_screen->x_res<<8) + (dev_drv->cur_screen->y_res<<20);
825 if(dev_drv->screen1) //device like rk2928,whic have one lcdc but two outputs
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;
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);
841 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
842 if(likely(inf->num_lcdc == 2))
844 pmy_info = inf->fb[0];
845 pmy_info->fbops->fb_pan_display(pmy_var,pmy_info);
849 printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!",__func__);
851 #elif defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
852 info->fbops->fb_pan_display(hdmi_var,info);
855 #if defined(CONFIG_NO_DUAL_DISP) //close backlight for device whic do not support dual display
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);
868 /******************************************
869 function:this function current only called by hdmi for
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 ******************************************/
876 int rk_fb_disp_scale(u8 scale_x, u8 scale_y,u8 lcdc_id)
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;
888 sprintf(name, "lcdc%d",lcdc_id);
889 for(i = 0; i < inf->num_lcdc; i++)
891 if(!strcmp(inf->lcdc_dev_drv[i]->name,name))
893 dev_drv = inf->lcdc_dev_drv[i];
898 if(i == inf->num_lcdc)
900 printk(KERN_ERR "%s driver not found!",name);
905 if((lcdc_id == 0) || (inf->num_lcdc == 1))
909 else if( (inf->num_lcdc == 2)&&(lcdc_id == 1))
911 info = inf->fb[dev_drv->num_layer];
915 screen_x = dev_drv->cur_screen->x_res;
916 screen_y = dev_drv->cur_screen->y_res;
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;
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;
932 var->nonstd |= (xpos<<8) + (ypos<<20);
933 var->grayscale &= 0xff;
934 var->grayscale |= (xsize<<8) + (ysize<<20);
937 info->fbops->fb_set_par(info);
943 static int rk_request_fb_buffer(struct fb_info *fbi,int fb_id)
945 struct resource *res;
946 struct resource *mem;
948 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
949 if (!strcmp(fbi->fix.id,"fb0"))
951 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb0 buf");
954 dev_err(&g_fb_pdev->dev, "failed to get memory for fb0 \n");
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);
967 #if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
968 res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "fb2 buf");
971 dev_err(&g_fb_pdev->dev, "failed to get win0 memory \n");
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;
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);
990 static int rk_release_fb_buffer(struct fb_info *fbi)
994 printk("no need release null fb buffer!\n");
997 if(!strcmp(fbi->fix.id,"fb1")||!strcmp(fbi->fix.id,"fb3")) //buffer for fb1 and fb3 are alloc by android
999 iounmap(fbi->screen_base);
1000 release_mem_region(fbi->fix.smem_start,fbi->fix.smem_len);
1004 static int init_layer_par(struct rk_lcdc_device_driver *dev_drv)
1007 struct layer_par * def_par = NULL;
1008 int num_par = dev_drv->num_layer;
1009 for(i = 0; i < num_par; i++)
1011 struct layer_par *par = NULL;
1012 par = kzalloc(sizeof(struct layer_par), GFP_KERNEL);
1015 printk(KERN_ERR "kzmalloc for layer_par fail!");
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;
1032 static int init_lcdc_device_driver(struct rk_lcdc_device_driver *dev_drv,
1033 struct rk_lcdc_device_driver *def_drv,int id)
1037 printk(KERN_ERR "default lcdc device driver is null!\n");
1042 printk(KERN_ERR "lcdc device driver is null!\n");
1045 sprintf(dev_drv->name, "lcdc%d",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;
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)
1086 bmp_logo = fb_find_logo(24);
1087 if (bmp_logo == NULL) {
1088 printk("%s error\n", __func__);
1094 static void fb_show_bmp_logo(struct fb_info *info, int rotate)
1096 unsigned char *src=bmp_logo->data;
1097 unsigned char *dst=info->screen_base;
1099 unsigned int Needwidth=(*(src-24)<<8)|(*(src-23));
1100 unsigned int Needheight=(*(src-22)<<8)|(*(src-21));
1102 for(i=0;i<Needheight;i++)
1103 memcpy(dst+info->var.xres*i*4, src+bmp_logo->width*i*4, Needwidth*4);
1108 int rk_fb_register(struct rk_lcdc_device_driver *dev_drv,
1109 struct rk_lcdc_device_driver *def_drv,int id)
1111 struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
1112 struct fb_info *fbi;
1117 printk("null lcdc device driver?");
1120 for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++)
1122 if(NULL==fb_inf->lcdc_dev_drv[i])
1124 fb_inf->lcdc_dev_drv[i] = dev_drv;
1125 fb_inf->lcdc_dev_drv[i]->id = id;
1130 if(i==RK30_MAX_LCDC_SUPPORT)
1132 printk("rk_fb_register lcdc out of support %d",i);
1136 init_lcdc_device_driver(dev_drv, def_drv,id);
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++)
1143 fbi= framebuffer_alloc(0, &g_fb_pdev->dev);
1146 dev_err(&g_fb_pdev->dev,">> fb framebuffer_alloc fail!");
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;
1160 fbi->var.bits_per_pixel = 16;
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
1179 rk_request_fb_buffer(fbi,fb_inf->num_fb);
1181 ret = register_framebuffer(fbi);
1184 printk("%s>>fb%d register_framebuffer fail!\n",__func__,fb_inf->num_fb);
1187 rkfb_create_sysfs(fbi);
1191 init_waitqueue_head(&dev_drv->vsync_info.wait);
1192 ret = device_create_file(fbi->dev,&dev_attr_vsync);
1195 dev_err(fbi->dev, "failed to create vsync file\n");
1197 dev_drv->vsync_info.thread = kthread_run(rk_fb_wait_for_vsync_thread,
1198 dev_drv, "fb-vsync");
1201 if (dev_drv->vsync_info.thread == ERR_PTR(-ENOMEM))
1203 dev_err(fbi->dev, "failed to run vsync thread\n");
1204 dev_drv->vsync_info.thread = NULL;
1206 dev_drv->vsync_info.active = 1;
1208 fb_inf->fb[fb_inf->num_fb] = fbi;
1209 printk("%s>>>>>%s\n",__func__,fb_inf->fb[fb_inf->num_fb]->fix.id);
1212 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
1213 if(dev_drv->screen_ctr_info->prop == PRMRY) //show logo for primary display device
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]);
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]);
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]);
1240 int rk_fb_unregister(struct rk_lcdc_device_driver *dev_drv)
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;
1250 printk(" no need to unregister null lcdc device driver!\n");
1254 for(i = 0; i < fb_num; i++)
1256 kfree(dev_drv->layer_par[i]);
1259 for(i=fb_index_base;i<(fb_index_base+fb_num);i++)
1261 fbi = fb_inf->fb[i];
1262 unregister_framebuffer(fbi);
1263 //rk_release_fb_buffer(fbi);
1264 framebuffer_release(fbi);
1266 fb_inf->lcdc_dev_drv[dev_drv->id]= NULL;
1274 #ifdef CONFIG_HAS_EARLYSUSPEND
1275 struct suspend_info {
1276 struct early_suspend early_suspend;
1277 struct rk_fb_inf *inf;
1280 static void rkfb_early_suspend(struct early_suspend *h)
1282 struct suspend_info *info = container_of(h, struct suspend_info,
1284 struct rk_fb_inf *inf = info->inf;
1286 for(i = 0; i < inf->num_lcdc; i++)
1288 if (!inf->lcdc_dev_drv[i])
1291 inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
1294 static void rkfb_early_resume(struct early_suspend *h)
1296 struct suspend_info *info = container_of(h, struct suspend_info,
1298 struct rk_fb_inf *inf = info->inf;
1300 for(i = 0; i < inf->num_lcdc; i++)
1302 if (!inf->lcdc_dev_drv[i])
1305 inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]); // data out
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,
1319 static int __devinit rk_fb_probe (struct platform_device *pdev)
1321 struct rk_fb_inf *fb_inf = NULL;
1324 /* Malloc rk_fb_inf and set it to pdev for drvdata */
1325 fb_inf = kzalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
1328 dev_err(&pdev->dev, ">>fb inf kmalloc fail!");
1331 platform_set_drvdata(pdev,fb_inf);
1333 #ifdef CONFIG_HAS_EARLYSUSPEND
1334 suspend_info.inf = fb_inf;
1335 register_early_suspend(&suspend_info.early_suspend);
1337 printk("rk fb probe ok!\n");
1341 static int __devexit rk_fb_remove(struct platform_device *pdev)
1343 struct rk_fb_inf *fb_inf = platform_get_drvdata(pdev);
1345 platform_set_drvdata(pdev, NULL);
1349 static void rk_fb_shutdown(struct platform_device *pdev)
1351 struct rk_fb_inf *inf = platform_get_drvdata(pdev);
1353 for(i = 0; i < inf->num_lcdc; i++)
1355 if (!inf->lcdc_dev_drv[i])
1358 if(inf->lcdc_dev_drv[i]->vsync_info.thread)
1359 kthread_stop(inf->lcdc_dev_drv[i]->vsync_info.thread);
1362 // platform_set_drvdata(pdev, NULL);
1363 #ifdef CONFIG_HAS_EARLYSUSPEND
1364 unregister_early_suspend(&suspend_info.early_suspend);
1368 static struct platform_driver rk_fb_driver = {
1369 .probe = rk_fb_probe,
1370 .remove = __devexit_p(rk_fb_remove),
1373 .owner = THIS_MODULE,
1375 .shutdown = rk_fb_shutdown,
1378 static int __init rk_fb_init(void)
1380 return platform_driver_register(&rk_fb_driver);
1383 static void __exit rk_fb_exit(void)
1385 platform_driver_unregister(&rk_fb_driver);
1388 subsys_initcall_sync(rk_fb_init);
1389 module_exit(rk_fb_exit);