rk30 lcdc: display lut support
[firefly-linux-kernel-4.4.55.git] / drivers / video / rk29_fb.c
old mode 100755 (executable)
new mode 100644 (file)
index 1688cf9..c1d1981
@@ -50,6 +50,7 @@
 
 #include <linux/hdmi.h>
 #endif
 
 #include <mach/iomux.h>
 #include <mach/gpio.h>
@@ -61,6 +62,9 @@
 
 #include "./display/screen/screen.h"
 
+#ifdef CONFIG_MFD_RK610
+#include "./display/lcd/rk610_lcd.h"
+#endif
 #define ANDROID_USE_THREE_BUFS  0       //android use three buffers to accelerate UI display in rgb plane
 #define CURSOR_BUF_SIZE         256     //RK2818 cursor need 256B buf
 int rk29_cursor_buf[CURSOR_BUF_SIZE];
@@ -243,7 +247,31 @@ typedef enum _TRSP_MODE
     TRSP_MASK,
     TRSP_INVAL
 } TRSP_MODE;
+#ifdef FB_WIMO_FLAG
+struct wimo_fb_info{
+       unsigned long bitperpixel;
+       unsigned long mode;
+       unsigned long xaff;
+       unsigned long yaff;
+       unsigned long xpos;
+       unsigned long ypos;
+       unsigned long xsize;
+       unsigned long ysize;
+       unsigned long src_y;
+       unsigned long src_uv;
+       unsigned long dst_width;
+       unsigned long dst_height;
+       //struct mutex fb_lock;
+       volatile unsigned long fb_lock;
 
+       
+};
+struct wimo_fb_info wimo_info;
+unsigned char* ui_buffer;
+unsigned char* ui_buffer_map;
+//unsigned char* overlay_buffer;
+//unsigned char* overlay_buffer_map;
+#endif
 
 struct platform_device *g_pdev = NULL;
 //static int win1fb_set_par(struct fb_info *info);
@@ -306,7 +334,15 @@ static int rk29fb_notify(struct rk29fb_inf *inf, unsigned long event)
 {
        return blocking_notifier_call_chain(&rk29fb_notifier_list, event, inf->cur_screen);
 }
+void rk29_lcd_set(bool on)
+{
+    struct rk29fb_info *mach_info = g_pdev->dev.platform_data;
+    if(on == 1 &&mach_info->io_enable)
+        mach_info->io_enable();       //open lcd out
+    else if(mach_info->io_disable)
+        mach_info->io_disable();  //close lcd out
 
+}
 int mcu_do_refresh(struct rk29fb_inf *inf)
 {
     if(inf->mcu_stopflush)  return 0;
@@ -1731,6 +1767,184 @@ static int fb0_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
     return 0;
 }
 
+#ifdef FB_WIMO_FLAG
+unsigned long temp_vv;
+static int frame_num = 0;
+static int wimo_set_buff(struct fb_info *info,unsigned long *temp)
+{
+       struct rk29fb_inf *inf = dev_get_drvdata(info->device);
+
+       ui_buffer = temp[0];
+       ui_buffer_map = ioremap(temp[0],temp[1]);
+       if(ui_buffer_map == NULL)
+       {
+               printk("can't map a buffer for ui\n");
+               return -EFAULT;
+       }
+
+       printk("ui_buffer %x  ",ui_buffer_map);
+       memset(&wimo_info,0,sizeof(wimo_info) );
+      wimo_info.mode = inf->video_mode;
+//     wimo_info.bitperpixel = var->bits_per_pixel;            
+    
+
+       wimo_info.dst_width = (temp[2] + 15) & 0xfff0;
+       wimo_info.dst_height = (temp[3] + 15) & 0xfff0;
+}
+static int wimo_get_buff(struct fb_info *info)
+{
+       
+       struct rk29_ipp_req overlay_req;
+       struct rk29_ipp_req overlay_req_1;
+       struct rk29fb_inf *inf = dev_get_drvdata(info->device);
+       int ret;
+       memset(&overlay_req, 0 , sizeof(overlay_req));
+       memset(&overlay_req_1, 0 , sizeof(overlay_req_1));
+       
+       if(inf->video_mode == 0 )
+       {
+               struct win0_par *par = info->par;
+               wimo_info.xpos = 0;
+               wimo_info.ypos = 0;
+               wimo_info.xsize = 0;
+               wimo_info.ysize = 0;
+               wimo_info.mode = 0;
+               if(par->format == 1)
+                       wimo_info.bitperpixel = 16;
+               else
+                       wimo_info.bitperpixel =32;// wimo_info.bitperpixel_fb1;
+               overlay_req.src0.YrgbMst = info->fix.smem_start + par->y_offset;//info->screen_base + par->y_offset;//info_buffer[8];
+               overlay_req.src0.CbrMst = info->fix.smem_start + par->y_offset + wimo_info.dst_width * wimo_info.dst_height;//dst_width*dst_height;//+ par->y_offset + dst_width*dst_height;//info_buffer[9];
+               overlay_req.src0.w = wimo_info.dst_width ;//dst_width;//info_buffer[2];
+               overlay_req.src0.h = wimo_info.dst_height ;//dst_height;//info_buffer[3];
+               overlay_req.src0.fmt = (wimo_info.bitperpixel == 16) ? 1 : 0;//3;
+               overlay_req.dst0.YrgbMst = ui_buffer;//overlay_buffer + info_buffer[4] + info_buffer[5] * dst_width;
+               overlay_req.dst0.CbrMst = ui_buffer + wimo_info.dst_width * wimo_info.dst_height;//dst_width*dst_height;//(unsigned char*) overlay_buffer + dst_width*dst_height +info_buffer[4] + (  info_buffer[5] * dst_width) / 2;// info_buffer[6] * info_buffer[7];
+               overlay_req.dst0.w = wimo_info.dst_width ;//dst_width;//info_buffer[6];
+               overlay_req.dst0.h = wimo_info.dst_height ;//dst_height;//info_buffer[7];
+               overlay_req.dst0.fmt = (wimo_info.bitperpixel== 16) ? 1 : 0;//3;3;
+               overlay_req.deinterlace_enable = 0;
+               overlay_req.timeout = 1000000;
+               overlay_req.src_vir_w = wimo_info.dst_width ;//dst_width;//info_buffer[2];
+               overlay_req.dst_vir_w = wimo_info.dst_width ;//dst_width;
+               overlay_req.flag = IPP_ROT_0;
+               ipp_blit_sync(&overlay_req);
+               
+               ret = 0;
+       }       
+       else
+       {
+
+               int err = 0;
+               static int wimo_time = 0;
+               unsigned long *overlay_buffer_map_temp;
+               unsigned long *map_temp;
+               unsigned long sign_memset = 0;
+               struct fb_var_screeninfo *var = &inf->fb1->var;
+               struct win0_par *par = inf->fb1->par;
+               wimo_info.mode = 1;
+       //      printk("overlay setbuffer in\n");
+       //      mutex_lock(&wimo_info.fb_lock);
+               wimo_info.fb_lock = 1;
+               {
+                       wimo_info.xaff = var->xres;
+                       wimo_info.yaff = var->yres;
+                       if((wimo_info.xpos != par->xpos) ||(wimo_info.ypos != par->ypos)||(wimo_info.xsize != par->xsize) ||(wimo_info.ysize != par->ysize))
+                       {
+                               wimo_info.xpos = par->xpos;
+                               wimo_info.ypos = par->ypos;
+                               wimo_info.xsize = par->xsize;
+                               wimo_info.ysize = par->ysize;
+                               sign_memset = 1;
+                               memset(ui_buffer_map,0,wimo_info.dst_height * wimo_info.dst_width);//dst_width*dst_height);
+                               memset(ui_buffer_map + wimo_info.dst_height * wimo_info.dst_width, 0x80,wimo_info.dst_height * wimo_info.dst_width / 2);//dst_width*dst_height,0x80,dst_width*dst_height/2);
+                               printk("wimo_info.xpos %d wimo_info.ypos %d wimo_info.xsize %d wimo_info.ysize %d\n",wimo_info.xpos, wimo_info.ypos, wimo_info.xsize, wimo_info.ysize );
+                       }
+               }
+               //printk("wimo_info.xpos %d wimo_info.ypos %d wimo_info.xsize %d wimo_info.ysize %d\n",wimo_info.xpos, wimo_info.ypos, wimo_info.xsize, wimo_info.ysize );
+               if(wimo_info.xaff * 3 < wimo_info.xsize || wimo_info.yaff * 3 < wimo_info.ysize)// 3time or bigger scale up
+               {
+                       unsigned long mid_width, mid_height;
+                       struct rk29_ipp_req overlay_req_1;
+                       if(wimo_info.xaff * 3 < wimo_info.xsize)
+                               mid_width = wimo_info.xaff * 3;
+                       else
+                               mid_width = wimo_info.xsize;
+                       
+                       if(wimo_info.yaff * 3 < wimo_info.ysize)
+                               mid_height =  wimo_info.yaff * 3;
+                       else
+                               mid_height = wimo_info.ysize;
+                       overlay_req.src0.YrgbMst = wimo_info.src_y;//info_buffer[8];
+                       overlay_req.src0.CbrMst = wimo_info.src_uv;//info_buffer[9];
+                       overlay_req.src0.w = wimo_info.xaff;// info_buffer[2];
+                       overlay_req.src0.h = wimo_info.yaff;// info_buffer[3];
+                       overlay_req.src0.fmt = 3;
+                       overlay_req.dst0.YrgbMst = ui_buffer + 2048000 ;//info_buffer[4] + info_buffer[5] * dst_width;   //С³ß´çƬԴÐèÒª2´Î·Å´ó£¬ËùÒÔ½«bufferµÄºó°ë¶ÎÓÃÓÚ»º´æ
+                       overlay_req.dst0.CbrMst = (unsigned char*) ui_buffer + mid_height * mid_width + 2048000;
+               
+                       overlay_req.dst0.w = mid_width;//info_buffer[6];
+                       overlay_req.dst0.h = mid_height;//info_buffer[7];
+                       overlay_req.dst0.fmt = 3;
+                       overlay_req.timeout = 100000;
+                       overlay_req.src_vir_w = wimo_info.xaff;//info_buffer[2];
+                       overlay_req.dst_vir_w = mid_width;//dst_width;
+                       overlay_req.flag = IPP_ROT_0;
+
+                       overlay_req_1.src0.YrgbMst = ui_buffer + 2048000;
+                       overlay_req_1.src0.CbrMst = (unsigned char*) ui_buffer + mid_height * mid_width + 2048000;
+                       overlay_req_1.src0.w = mid_width;
+                       overlay_req_1.src0.h = mid_height;// info_buffer[3];
+                       overlay_req_1.src0.fmt = 3;
+                       overlay_req_1.dst0.YrgbMst = ui_buffer + ((wimo_info.xpos + 1)&0xfffe) + wimo_info.ypos * wimo_info.dst_width;//info_buffer[4] + info_buffer[5] * dst_width;
+                       overlay_req_1.dst0.CbrMst =(unsigned char*) ui_buffer + wimo_info.dst_width * wimo_info.dst_height + ((wimo_info.xpos + 1)&0xfffe) + ( wimo_info.ypos  / 2)* wimo_info.dst_width ;
+                       
+                       overlay_req_1.dst0.w = wimo_info.xsize;//info_buffer[6];
+                       overlay_req_1.dst0.h = wimo_info.ysize;//info_buffer[7];
+                       overlay_req_1.dst0.fmt = 3;
+                       overlay_req_1.timeout = 100000;
+                       overlay_req_1.src_vir_w = mid_width;//info_buffer[2];
+                       overlay_req_1.dst_vir_w = wimo_info.dst_width;//dst_width;
+                       overlay_req_1.flag = IPP_ROT_0;
+                       
+
+                       err = ipp_blit_sync(&overlay_req);
+                       dmac_flush_range(ui_buffer_map,ui_buffer_map + wimo_info.dst_height * wimo_info.dst_width * 3/2);//dst_width*dst_height*3/2);
+                       err = ipp_blit_sync(&overlay_req_1);
+       
+               }
+               else
+               {
+                       overlay_req.src0.YrgbMst = wimo_info.src_y;//info_buffer[8];
+                       overlay_req.src0.CbrMst = wimo_info.src_uv;//info_buffer[9];
+                       overlay_req.src0.w = wimo_info.xaff;// info_buffer[2];
+                       overlay_req.src0.h = wimo_info.yaff;// info_buffer[3];
+                       overlay_req.src0.fmt = 3;
+                       overlay_req.dst0.YrgbMst = ui_buffer + ((wimo_info.xpos + 1)&0xfffe) + wimo_info.ypos * wimo_info.dst_width;//info_buffer[4] + info_buffer[5] * dst_width;
+                       overlay_req.dst0.CbrMst =(unsigned char*) ui_buffer + wimo_info.dst_width * wimo_info.dst_height + ((wimo_info.xpos + 1)&0xfffe) + ( wimo_info.ypos  / 2)* wimo_info.dst_width ;
+                       
+                       overlay_req.dst0.w = wimo_info.xsize;//wimo_info.xsize;//wimo_info.xaff;// wimo_info.xsize;//info_buffer[6];
+                       overlay_req.dst0.h = (wimo_info.ysize + 1) & 0xfffe;//(wimo_info.ysize + 1) & 0xfffe;//wimo_info.yaff;//(wimo_info.ysize + 1) & 0xfffe;//info_buffer[7];
+                       overlay_req.dst0.fmt = 3;
+                       overlay_req.timeout = 100000;
+                       overlay_req.src_vir_w = wimo_info.xaff;//info_buffer[2];
+                       overlay_req.dst_vir_w = wimo_info.dst_width;//wimo_info.dst_width;//wimo_info.yaff;//wimo_info.dst_width;//dst_width;
+                       overlay_req.flag = IPP_ROT_0;
+                       
+                       dmac_flush_range(ui_buffer_map,ui_buffer_map + wimo_info.dst_height * wimo_info.dst_width * 3/2);//dst_width*dst_height*3/2);
+                       err = ipp_blit_sync(&overlay_req);
+               
+               }
+       //      printk("overlay setbuffer exit\n");
+               ret = 1;
+               wimo_info.fb_lock = 0;
+       }
+       
+               
+       return ret;
+}
+#endif
 static int fb0_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 {
     struct rk29fb_inf *inf = dev_get_drvdata(info->device);
@@ -1829,6 +2043,52 @@ static int fb0_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
             if(copy_to_user((void*)arg, &en, 4))  return -EFAULT;
             break;
                }
+#ifdef FB_WIMO_FLAG
+       case FB0_IOCTL_SET_BUF:
+               {
+                       unsigned long temp[4];
+                       copy_from_user(temp, (void*)arg, 20);
+                       wimo_set_buff( info,temp);
+                       
+               }
+               break;
+       case FB0_IOCTL_CLOSE_BUF:
+               {
+                       if(ui_buffer != NULL && ui_buffer_map !=NULL )
+                       {
+                               iounmap(ui_buffer_map);
+                               ui_buffer_map = 0;
+                               ui_buffer = 0;
+                               memset(&wimo_info,0,sizeof(wimo_info));
+                       }
+                       else
+                               printk("somethint wrong with wimo in close");
+                               
+               }
+               break;
+       
+       case FB0_IOCTL_COPY_CURBUF:
+               {
+                       unsigned long temp_data[3];
+                       copy_from_user(&temp_vv, (void*)arg, 4);
+                       if(ui_buffer != NULL && ui_buffer_map !=NULL )
+                       {
+                               temp_data[1] = wimo_get_buff(info);
+                               temp_data[0] = wimo_info.bitperpixel;
+                               
+                       }
+                       else
+                       {
+                               temp_data[1] = 1;
+                               temp_data[0] = wimo_info.bitperpixel;
+                               printk("somethint wrong with wimo in getbuf");
+                       }
+                       temp_data[2] = frame_num++;
+                       //printk("FB0_IOCTL_COPY_CURBUF %d %d %d\n",temp_data[0],temp_data[1],temp_data[2]);
+                       copy_to_user((void*)arg, &temp_data, 12);
+                       break;
+               }
+#endif
    default:
         break;
     }
@@ -2397,6 +2657,14 @@ static int fb1_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
     case FB1_IOCTL_SET_YUV_ADDR:    //set y&uv address to register direct
         {
             u32 yuv_phy[2];
+#ifdef FB_WIMO_FLAG
+       //      printk("FB1_IOCTL_SET_YUV_ADDR1 \n");
+       //      while(wimo_info.fb_lock)
+       //              {
+       //              msleep(10);
+       //              }
+       //      printk("FB1_IOCTL_SET_YUV_ADDR 2\n");
+#endif
             if (copy_from_user(yuv_phy, argp, 8))
                            return -EFAULT;
 #ifdef CONFIG_FB_ROTATE_VIDEO 
@@ -2411,6 +2679,11 @@ static int fb1_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
             fix0->mmio_start = yuv_phy[1];
             yuv_phy[0] += par->y_offset;
             yuv_phy[1] += par->c_offset;
+#ifdef FB_WIMO_FLAG
+             wimo_info.src_y = yuv_phy[0]; 
+             wimo_info.src_uv = yuv_phy[1]; 
+               
+#endif
          
             #if 0
                if((var->rotate == 90) ||(var->rotate == 270))
@@ -2661,10 +2934,19 @@ int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable )
 
     if(inf->cur_screen->standby)    inf->cur_screen->standby(1);
     // operate the display_on pin to power down the lcd
-   
+#ifdef CONFIG_HDMI_DUAL_DISP
+       if(inf->panel1_info.sscreen_get!=NULL)
+       inf->panel1_info.sscreen_get(&inf->panel1_info,inf->panel2_info.hdmi_resolution);
+       else
+               printk("warnig : LCD driver do not support dual display");
+       if(inf->panel1_info.sscreen_set!=NULL)
+       inf->panel1_info.sscreen_set(&inf->panel1_info,enable);
+       else
+               printk("warnig : LCD driver do not support dual display");
+#else
     if(enable && mach_info->io_disable)mach_info->io_disable();  //close lcd out
     else if (mach_info->io_enable)mach_info->io_enable();       //open lcd out
-    
+#endif
     load_screen(inf->fb0, 0);
        mcu_refresh(inf);
 
@@ -2672,6 +2954,7 @@ int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable )
     fb0_set_par(inf->fb0);
     LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE,  v_BLACK_MODE(0));
     LcdWrReg(inf, REG_CFG_DONE, 0x01);
+
     rk29fb_notify(inf, enable ? RK29FB_EVENT_HDMI_ON : RK29FB_EVENT_HDMI_OFF);
     return 0;
 }
@@ -2809,10 +3092,13 @@ static void rk29fb_early_suspend(struct early_suspend *h)
 #ifdef CONFIG_CLOSE_WIN1_DYNAMIC   
      cancel_delayed_work_sync(&rk29_win1_check_work);
 #endif  
-
+#ifdef CONFIG_HDMI_DUAL_DISP
+    if(mach_info->io_disable)  // close lcd pwr when output screen is lcd
+       mach_info->io_disable();  //close lcd out 
+#else
     if((inf->cur_screen != &inf->panel2_info) && mach_info->io_disable)  // close lcd pwr when output screen is lcd
        mach_info->io_disable();  //close lcd out 
-
+#endif
        if(inf->cur_screen->standby)
        {
                fbprintk(">>>>>> power down the screen! \n");
@@ -2897,10 +3183,13 @@ static void rk29fb_early_resume(struct early_suspend *h)
     usleep_range(10*1000, 10*1000);
     memcpy((u8*)inf->preg, (u8*)&inf->regbak, 0xa4);  //resume reg
     usleep_range(40*1000, 40*1000);
-    
+    #ifdef CONFIG_HDMI_DUAL_DISP
+    if(mach_info->io_enable)  // open lcd pwr when output screen is lcd
+       mach_info->io_enable();  //close lcd out 
+    #else
     if((inf->cur_screen != &inf->panel2_info) && mach_info->io_enable)  // open lcd pwr when output screen is lcd
        mach_info->io_enable();  //close lcd out 
-               
+    #endif
 }
 
 static struct suspend_info suspend_info = {
@@ -2910,7 +3199,7 @@ static struct suspend_info suspend_info = {
 };
 #endif
 struct fb_info *g_fb0_inf = NULL;  //add cym@rk 20101027 for charger logo
-static int __init rk29fb_probe (struct platform_device *pdev)
+static int __devinit rk29fb_probe (struct platform_device *pdev)
 {
     struct rk29fb_inf *inf = NULL;
     struct resource *res = NULL;
@@ -2943,6 +3232,7 @@ static int __init rk29fb_probe (struct platform_device *pdev)
    #else
     set_lcd_info(&inf->panel1_info, mach_info->lcd_info);
    #endif
+
     inf->cur_screen = &inf->panel1_info;
     screen = inf->cur_screen;
     if(SCREEN_NULL==screen->type)
@@ -3225,7 +3515,9 @@ static int __init rk29fb_probe (struct platform_device *pdev)
             goto release_irq;
         }
     }
-
+ #ifdef CONFIG_MFD_RK610
+    rk610_lcd_scaler_set_param(&inf->panel1_info,0);
+ #endif
 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
     fb0_set_par(inf->fb0);
     if (fb_prepare_logo(inf->fb0, FB_ROTATE_UR)) {
@@ -3266,7 +3558,7 @@ release_drvdata:
        return ret;
 }
 
-static int rk29fb_remove(struct platform_device *pdev)
+static int __devexit rk29fb_remove(struct platform_device *pdev)
 {
     struct rk29fb_inf *inf = platform_get_drvdata(pdev);
     struct fb_info *info = NULL;
@@ -3391,7 +3683,7 @@ static void rk29fb_shutdown(struct platform_device *pdev)
 
 static struct platform_driver rk29fb_driver = {
        .probe          = rk29fb_probe,
-       .remove         = rk29fb_remove,
+       .remove         = __devexit_p(rk29fb_remove),
        .driver         = {
                .name   = "rk29-fb",
                .owner  = THIS_MODULE,