rk30 fb: add pan_display support
authoryxj <yxj@I7-CH.(none)>
Mon, 26 Mar 2012 02:05:35 +0000 (10:05 +0800)
committeryxj <yxj@I7-CH.(none)>
Mon, 26 Mar 2012 02:06:35 +0000 (10:06 +0800)
drivers/video/rockchip/chips/rk30_lcdc.c
drivers/video/rockchip/rk_fb.c
drivers/video/rockchip/rk_fb.h

index 149f24dd4236b25d49fdd7a1e98b60e4e7c030ab..db770eff652e9c1a682bbcf152a9f16eb10eb867 100644 (file)
@@ -35,6 +35,7 @@
 
 
 static int dbg_thresd = 0;
+module_param(dbg_thresd, int, S_IRUGO|S_IWUSR);
 #define DBG(x...) do { if(unlikely(dbg_thresd)) printk(KERN_INFO x); } while (0)
 
 
@@ -84,7 +85,6 @@ int rk30_load_screen(struct rk30_lcdc_device*lcdc_dev, bool initscreen)
        u16 right_margin = screen->right_margin;
        u16 lower_margin = screen->lower_margin;
        u16 x_res = screen->x_res, y_res = screen->y_res;
-       u32 aclk_rate = 150000000;
 
        // set the rgb or mcu
 
@@ -211,6 +211,7 @@ int rk30_load_screen(struct rk30_lcdc_device*lcdc_dev, bool initscreen)
                screen->init();
        }
        printk("%s>>>>>ok!\n",__func__);
+       return 0;
 }
 
 static int mcu_refresh(struct rk30_lcdc_device *lcdc_dev)
@@ -281,21 +282,47 @@ static int rk30_lcdc_blank(struct rk_lcdc_device_driver*fb_drv,int layer_id,int
     return 0;
 }
 
+static  int win0_display(struct rk30_lcdc_device *lcdc_dev,struct layer_par *par )
+{
+       u32 y_addr;
+       u32 uv_addr;
+       y_addr = par->smem_start + par->y_offset;
+       uv_addr = par->cbr_start + par->c_offset;
+       DBG(KERN_INFO "%s:y_addr:0x%x>>uv_addr:0x%x\n",__func__,y_addr,uv_addr);
+       LcdWrReg(lcdc_dev, WIN0_YRGB_MST0, y_addr);
+       LcdWrReg(lcdc_dev,WIN0_CBR_MST0,uv_addr);
+       LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);  // write any value to  REG_CFG_DONE let config become effective
+       return 0;
+       
+}
+
+static  int win1_display(struct rk30_lcdc_device *lcdc_dev,struct layer_par *par )
+{
+       u32 y_addr;
+       u32 uv_addr;
+       y_addr = par->smem_start + par->y_offset;
+       uv_addr = par->cbr_start + par->c_offset;
+       DBG(KERN_INFO "%s>>y_addr:0x%x>>uv_addr:0x%x\n",__func__,y_addr,uv_addr);
+       LcdWrReg(lcdc_dev, WIN1_YRGB_MST, y_addr);
+       LcdWrReg(lcdc_dev,WIN1_CBR_MST,uv_addr);
+       LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
+
+       return 0;
+}
+
 static  int win0_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
        struct layer_par *par )
 {
     u32 xact, yact, xvir, yvir, xpos, ypos;
     u32 ScaleYrgbX,ScaleYrgbY, ScaleCbrX, ScaleCbrY;
-    u32 y_addr,uv_addr;
-
+    
     xact = par->xact;                      /*active (origin) picture window width/height               */
     yact = par->yact;
-    xvir = par->xvir;          /* virtual resolution           */
+    xvir = par->xvir;                     /* virtual resolution                */
     yvir = par->yvir;
     xpos = par->xpos+screen->left_margin + screen->hsync_len;
     ypos = par->ypos+screen->upper_margin + screen->vsync_len;
-    y_addr = par->smem_start + par->y_offset;
-    uv_addr = par->cbr_start + par->c_offset;
+   
        
     ScaleYrgbX = CalScale(xact, par->xsize); //both RGB and yuv need this two factor
     ScaleYrgbY = CalScale(yact, par->ysize);
@@ -317,10 +344,8 @@ static  int win0_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
            break;
     }
 
-       DBG("%s>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>ypos:%d>>y_addr:0x%x>>uv_addr:0x%x\n",
-               __func__,par->format,xact,yact,par->xsize,par->ysize,xvir,yvir,ypos,y_addr,uv_addr);
-    LcdWrReg(lcdc_dev, WIN0_YRGB_MST0, y_addr);
-    LcdWrReg(lcdc_dev,WIN0_CBR_MST0,uv_addr);
+       DBG("%s>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>ypos:%d>>\n",
+               __func__,par->format,xact,yact,par->xsize,par->ysize,xvir,yvir,ypos);
     LcdMskReg(lcdc_dev,SYS_CTRL1,  m_W0_FORMAT , v_W0_FORMAT(par->format));            //(inf->video_mode==0)
     LcdWrReg(lcdc_dev, WIN0_ACT_INFO,v_ACT_WIDTH(xact) | v_ACT_HEIGHT(yact));
     LcdWrReg(lcdc_dev, WIN0_DSP_ST, v_DSP_STX(xpos) | v_DSP_STY(ypos));
@@ -348,8 +373,6 @@ static  int win0_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
             LcdWrReg(lcdc_dev, WIN0_VIR,v_RGB888_VIRWIDTH(xvir));
             break;
     }
-
-    LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
        
     return 0;
 
@@ -361,20 +384,18 @@ static int win1_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
 {
        u32 xact, yact, xvir, yvir, xpos, ypos;
        u32 ScaleYrgbX,ScaleYrgbY, ScaleCbrX, ScaleCbrY;
-       u32 y_addr,uv_addr;
-       xact = par->xact;                           /* visible resolution               */
+       
+       xact = par->xact;                       
        yact = par->yact;
-       xvir = par->xvir;               /* virtual resolution           */
+       xvir = par->xvir;               
        yvir = par->yvir;
        xpos = par->xpos+screen->left_margin + screen->hsync_len;
        ypos = par->ypos+screen->upper_margin + screen->vsync_len;
-       y_addr = par->smem_start + par->y_offset;
-       uv_addr = par->cbr_start + par->c_offset;
        
        ScaleYrgbX = CalScale(xact, par->xsize);
        ScaleYrgbY = CalScale(yact, par->ysize);
-       DBG("%s>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>ypos:%d>>y_addr:0x%x>>uv_addr:0x%x\n",
-               __func__,par->format,xact,yact,par->xsize,par->ysize,xvir,yvir,ypos,y_addr,uv_addr);
+       DBG("%s>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>ypos:%d>>\n",
+               __func__,par->format,xact,yact,par->xsize,par->ysize,xvir,yvir,ypos);
        switch (par->format)
        {
                case YUV422:// yuv422
@@ -396,8 +417,6 @@ static int win1_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
     LcdWrReg(lcdc_dev, WIN1_SCL_FACTOR_YRGB, v_X_SCL_FACTOR(ScaleYrgbX) | v_Y_SCL_FACTOR(ScaleYrgbY));
     LcdWrReg(lcdc_dev, WIN1_SCL_FACTOR_CBR,  v_X_SCL_FACTOR(ScaleCbrX) | v_Y_SCL_FACTOR(ScaleCbrY));
     LcdMskReg(lcdc_dev, SYS_CTRL1, m_W1_EN|m_W1_FORMAT, v_W1_EN(1)|v_W1_FORMAT(par->format));
-    LcdWrReg(lcdc_dev, WIN1_YRGB_MST, y_addr);
-    LcdWrReg(lcdc_dev,WIN1_CBR_MST,uv_addr);
     LcdWrReg(lcdc_dev, WIN1_ACT_INFO,v_ACT_WIDTH(xact) | v_ACT_HEIGHT(yact));
     LcdWrReg(lcdc_dev, WIN1_DSP_ST,v_DSP_STX(xpos) | v_DSP_STY(ypos));
     LcdWrReg(lcdc_dev, WIN1_DSP_INFO,v_DSP_WIDTH(par->xsize) | v_DSP_HEIGHT(par->ysize));
@@ -424,18 +443,21 @@ static int win1_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
             LcdWrReg(lcdc_dev, WIN1_VIR,v_RGB888_VIRWIDTH(xvir));
             break;
     }
-    
-       LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
-
+       
     return 0;
 }
 
 static int rk30_lcdc_set_par(struct rk_lcdc_device_driver *fb_drv,int layer_id)
 {
        struct rk30_lcdc_device *lcdc_dev=NULL;
-       struct layer_par *par = &fb_drv->layer_par[0];
-       rk_screen *screen = &fb_drv->screen;
        struct lcdc_info * info = platform_get_drvdata(g_lcdc_pdev);
+       struct layer_par *par = NULL;
+       rk_screen *screen = &fb_drv->screen;
+       if(!screen)
+       {
+               printk(KERN_ERR "screen is null!\n");
+               return -ENOENT;
+       }
        if(!strcmp(fb_drv->name,"lcdc0"))
        {
                lcdc_dev =  &(info->lcdc0); 
@@ -445,24 +467,52 @@ static int rk30_lcdc_set_par(struct rk_lcdc_device_driver *fb_drv,int layer_id)
                lcdc_dev = &(info->lcdc1);
        }
        
-       if(!screen)
-       {
-               printk(KERN_ERR "screen is null!\n");
-       }
+       
        if(layer_id==0)
        {
-        win0_set_par(lcdc_dev,screen,par);
+               par = &(fb_drv->layer_par[0]);
+               win0_set_par(lcdc_dev,screen,par);
        }
        else if(layer_id==1)
        {
-        win1_set_par(lcdc_dev,screen,&(fb_drv->layer_par[1]));
+               par = &(fb_drv->layer_par[1]);
+               win1_set_par(lcdc_dev,screen,par);
        }
        
        return 0;
 }
-int rk30_lcdc_pan(struct rk_lcdc_device_driver * dev_drv,int layer_id)
+
+int rk30_lcdc_pan_display(struct rk_lcdc_device_driver * dev_drv,int layer_id)
 {
+       struct rk30_lcdc_device *lcdc_dev=NULL;
+       struct lcdc_info * info = platform_get_drvdata(g_lcdc_pdev);
+       struct layer_par *par = NULL;
+       rk_screen *screen = &dev_drv->screen;
+       if(!screen)
+       {
+               printk(KERN_ERR "screen is null!\n");
+               return -ENOENT; 
+       }
+       if(!strcmp(dev_drv->name,"lcdc0"))
+       {
+               lcdc_dev =  &(info->lcdc0); 
+       }
+       else if(!strcmp(dev_drv->name,"lcdc1"))
+       {
+               lcdc_dev = &(info->lcdc1);
+       }
+       
+       
+       if(layer_id==0)
+       {
+               par = &(dev_drv->layer_par[0]);
+               win0_display(lcdc_dev,par);
+       }
+       else if(layer_id==1)
+       {
+               par = &(dev_drv->layer_par[1]);
+               win1_display(lcdc_dev,par);
+       }
        
     return 0;
 }
@@ -516,9 +566,9 @@ static struct rk_lcdc_device_driver lcdc0_driver = {
        .ioctl                  = rk30_lcdc_ioctl,
        .suspend                = rk30_lcdc_suspend,
        .resume                 = rk30_lcdc_resume,
-       .set_par       = rk30_lcdc_set_par,
-       .blank         = rk30_lcdc_blank,
-       .pan           = rk30_lcdc_pan,
+       .set_par                = rk30_lcdc_set_par,
+       .blank                  = rk30_lcdc_blank,
+       .pan_display            = rk30_lcdc_pan_display,
 };
 static struct rk_lcdc_device_driver lcdc1_driver = {
        .name                   = "lcdc1",
@@ -527,9 +577,9 @@ static struct rk_lcdc_device_driver lcdc1_driver = {
        .ioctl                  = rk30_lcdc_ioctl,
        .suspend                = rk30_lcdc_suspend,
        .resume                 = rk30_lcdc_resume,
-       .set_par       = rk30_lcdc_set_par,
-       .blank         = rk30_lcdc_blank,
-       .pan           = rk30_lcdc_pan,
+       .set_par                = rk30_lcdc_set_par,
+       .blank                  = rk30_lcdc_blank,
+       .pan_display            = rk30_lcdc_pan_display,
 };
 
 static int __devinit rk30_lcdc_probe (struct platform_device *pdev)
index 14cea5338419745718349c34898b38c9827557dc..c03ce4b202a761c497bd8c0124835c442680874b 100644 (file)
@@ -116,6 +116,64 @@ static int rk_fb_release(struct fb_info *info,int user)
 
 static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+       struct rk_fb_inf *inf = dev_get_drvdata(info->device);
+       struct fb_fix_screeninfo *fix = &info->fix;
+       struct rk_lcdc_device_driver * dev_drv = NULL;
+       struct layer_par *par = NULL;
+       int layer_id = 0;
+       u32 xoffset = var->xoffset;             // offset from virtual to visible 
+       u32 yoffset = var->yoffset;                             
+       u32 xvir = var->xres_virtual;
+       u8 data_format = var->nonstd&0xff;
+       if(!strcmp(fix->id,"fb1")){
+               dev_drv = inf->rk_lcdc_device[0];
+               par = &dev_drv->layer_par[0];
+               layer_id = 0;
+       }else if(!strcmp(fix->id,"fb0")){
+               dev_drv = inf->rk_lcdc_device[0];
+               par = &dev_drv->layer_par[1];
+               layer_id = 1;
+       }else if(!strcmp(fix->id,"fb3")){
+               dev_drv = inf->rk_lcdc_device[1];
+               par = &dev_drv->layer_par[0];
+               layer_id = 0;
+       }else if(!strcmp(fix->id,"fb2")){
+               dev_drv = inf->rk_lcdc_device[1];
+               par = &dev_drv->layer_par[1];
+               layer_id = 1;
+       }else{
+               dev_drv = inf->rk_lcdc_device[0];
+               par = &dev_drv->layer_par[1];
+               layer_id = 0;
+       }
+       switch (par->format)
+       {
+               case ARGB888:
+                       par->y_offset = (yoffset*xvir + xoffset)*4;
+                       break;
+               case  RGB888:
+                       par->y_offset = (yoffset*xvir + xoffset)*3;
+                       break;
+               case RGB565:
+                       par->y_offset = (yoffset*xvir + xoffset)*2;
+                       break;
+               case  YUV422:
+                       par->y_offset = yoffset*xvir + xoffset;
+                       par->c_offset = par->y_offset;
+                       break;
+               case  YUV420:
+                       par->y_offset = yoffset*xvir + xoffset;
+                       par->c_offset = (yoffset>>1)*xvir + xoffset;
+                       break;
+               case  YUV444 : // yuv444
+                       par->y_offset = yoffset*xvir + xoffset;
+                       par->c_offset = yoffset*2*xvir +(xoffset<<1);
+                       break;
+               default:
+                       printk("un supported format:0x%x\n",data_format);
+                       return -EINVAL;
+       }
+       dev_drv->pan_display(dev_drv,layer_id);
        return 0;
 }
 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,
@@ -345,15 +403,15 @@ static int rk_fb_set_par(struct fb_info *info)
     switch (data_format)
     {
        case HAL_PIXEL_FORMAT_RGBA_8888 :      // rgb
+       case HAL_PIXEL_FORMAT_RGBX_8888: 
                par->format = ARGB888;
                fix->line_length = 4 * xvir;
                par->y_offset = (yoffset*xvir + xoffset)*4;
                break;
-       case HAL_PIXEL_FORMAT_RGBX_8888: 
        case HAL_PIXEL_FORMAT_RGB_888 :
                par->format = RGB888;
-               fix->line_length = 4 * xvir;
-               par->y_offset = (yoffset*xvir + xoffset)*4;
+               fix->line_length = 3 * xvir;
+               par->y_offset = (yoffset*xvir + xoffset)*3;
                break;
        case HAL_PIXEL_FORMAT_RGB_565:  //RGB565
                par->format = RGB565;
@@ -532,7 +590,7 @@ static int request_fb_buffer(struct fb_info *fbi,int fb_id)
             fbi->fix.smem_len = res->end - res->start + 1;
             fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
             memset(fbi->screen_base, 0, fbi->fix.smem_len);
-           printk("phy:%x\n>>vir:%x\n",fbi->fix.smem_start,fbi->screen_base);
+           printk("phy:%lx\n>>vir:%p\n",fbi->fix.smem_start,fbi->screen_base);
         #ifdef CONFIG_FB_WORK_IPP
         /* alloc ipp buf for rotate */
             res = platform_get_resource_byname(g_fb_pdev, IORESOURCE_MEM, "ipp buf");
@@ -635,6 +693,7 @@ int rk_fb_register(struct rk_lcdc_device_driver *dev_drv)
         fb_set_cmap(&fb_inf->fb[fb_inf->num_fb-2]->cmap, fb_inf->fb[fb_inf->num_fb-2]);
         fb_show_logo(fb_inf->fb[fb_inf->num_fb-2], FB_ROTATE_UR);
         fb_inf->fb[fb_inf->num_fb-2]->fbops->fb_blank(FB_BLANK_UNBLANK, fb_inf->fb[fb_inf->num_fb-2]);
+       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]);
     }
 #endif
        return 0;
index 1a7b37d15f7d0bace3535c32185cd07619cc97dc..591ebe70b2e44bcea1bb31b96a880202a19910fa 100644 (file)
@@ -187,7 +187,7 @@ struct rk_lcdc_device_driver{
        int (*resume)(struct layer_par *layer_par);
        int (*blank)(struct rk_lcdc_device_driver *rk_fb_dev_drv,int layer_id,int blank_mode);
        int (*set_par)(struct rk_lcdc_device_driver *rk_fb_dev_drv,int layer_id);
-       int (*pan)(struct rk_lcdc_device_driver *rk_fb_dev_drv,int layer_id);
+       int (*pan_display)(struct rk_lcdc_device_driver *rk_fb_dev_drv,int layer_id);
        
 };