From: yxj Date: Mon, 26 Mar 2012 02:05:35 +0000 (+0800) Subject: rk30 fb: add pan_display support X-Git-Tag: firefly_0821_release~9588 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=80435436d1e6d9ef39acc8ea7b1a9b57077eaf93;p=firefly-linux-kernel-4.4.55.git rk30 fb: add pan_display support --- diff --git a/drivers/video/rockchip/chips/rk30_lcdc.c b/drivers/video/rockchip/chips/rk30_lcdc.c index 149f24dd4236..db770eff652e 100644 --- a/drivers/video/rockchip/chips/rk30_lcdc.c +++ b/drivers/video/rockchip/chips/rk30_lcdc.c @@ -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) diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index 14cea5338419..c03ce4b202a7 100644 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -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; diff --git a/drivers/video/rockchip/rk_fb.h b/drivers/video/rockchip/rk_fb.h index 1a7b37d15f7d..591ebe70b2e4 100644 --- a/drivers/video/rockchip/rk_fb.h +++ b/drivers/video/rockchip/rk_fb.h @@ -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); };