mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
rk30 fb: add pan_display support
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user