rkfb:modify to implement dual display on rk2928

This commit is contained in:
yxj 2012-08-29 13:06:18 +08:00
parent 1889aab5c7
commit ef457e753e
2 changed files with 65 additions and 20 deletions

View File

@ -346,7 +346,7 @@ static int rk_fb_set_par(struct fb_info *info)
struct fb_fix_screeninfo *fix = &info->fix;
struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
struct layer_par *par = NULL;
rk_screen *screen =dev_drv->screen0;
rk_screen *screen =dev_drv->cur_screen;
struct fb_info * info2 = NULL;
struct rk_lcdc_device_driver * dev_drv1 = NULL;
struct layer_par *par2 = NULL;
@ -388,17 +388,31 @@ static int rk_fb_set_par(struct fb_info *info)
}
}
if(var->grayscale>>8)
if(var->grayscale>>8) //if the application has specific the horizontal and vertical display size
{
xsize = (var->grayscale>>8) & 0xfff; //visiable size in panel ,for vide0
ysize = (var->grayscale>>20) & 0xfff;
}
else
else //ohterwise full screen display
{
xsize = screen->x_res;
ysize = screen->y_res;
}
if(screen->lcdc_id == 0) //this is for device like rk2928 ,whic have one lcdc but two display outputs
{
dev_drv->screen0->xsize = xsize;
dev_drv->screen0->ysize = ysize;
dev_drv->screen0->xpos = xpos;
dev_drv->screen0->ypos = ypos;
}
else
{
dev_drv->screen1->xsize = xsize;
dev_drv->screen1->ysize = ysize;
dev_drv->screen1->xpos = xpos;
dev_drv->screen1->ypos = ypos;
}
/* calculate y_offset,c_offset,line_length,cblen and crlen */
#if 1
switch (data_format)
@ -607,6 +621,7 @@ int rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id)
int ret;
int i;
int layer_id;
sprintf(name, "lcdc%d",lcdc_id);
for(i = 0; i < inf->num_lcdc; i++)
{
@ -634,8 +649,24 @@ int rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id)
info = inf->fb[2];
}
layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
if(!enable)
if(dev_drv->screen1) //device like rk2928 ,have only one lcdc but two outputs
{
if(enable)
{
memcpy(dev_drv->screen1,screen,sizeof(rk_screen ));
dev_drv->screen1->lcdc_id = 1;
dev_drv->cur_screen = dev_drv->screen1;
}
else
{
dev_drv->cur_screen = dev_drv->screen0;
}
}
layer_id = dev_drv->fb_get_layer(dev_drv,info->fix.id);
if(!enable && !dev_drv->screen1) //only double lcdc device need to close
{
if(dev_drv->layer_par[layer_id]->state)
{
@ -665,6 +696,14 @@ int rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id)
#endif
hdmi_var->grayscale &= 0xff;
hdmi_var->grayscale |= (dev_drv->cur_screen->x_res<<8) + (dev_drv->cur_screen->y_res<<20);
if(dev_drv->screen1) //device like rk2928,whic have one lcdc but two outputs
{
info->var.nonstd &= 0xff;
info->var.nonstd |= (dev_drv->cur_screen->xpos<<8) + (dev_drv->cur_screen->ypos<<20);
info->var.grayscale &= 0xff;
info->var.grayscale |= (dev_drv->cur_screen->x_res<<8) + (dev_drv->cur_screen->y_res<<20);
}
ret = info->fbops->fb_open(info,1);
ret = dev_drv->load_screen(dev_drv,1);
ret = info->fbops->fb_set_par(info);
@ -696,6 +735,7 @@ int rk_fb_disp_scale(u8 scale_x, u8 scale_y,u8 lcdc_id)
char name[6];
int i;
printk("scale_x:%x>>scale_y:%d\n",scale_x,scale_y);
sprintf(name, "lcdc%d",lcdc_id);
for(i = 0; i < inf->num_lcdc; i++)
{
@ -952,9 +992,9 @@ int rk_fb_register(struct rk_lcdc_device_driver *dev_drv,
init_lcdc_device_driver(dev_drv, def_drv,id);
if(dev_drv->screen_ctr_info->set_screen_info)
{
dev_drv->screen_ctr_info->set_screen_info(dev_drv->screen0,
dev_drv->screen_ctr_info->set_screen_info(dev_drv->cur_screen,
dev_drv->screen_ctr_info->lcd_info);
if(SCREEN_NULL==dev_drv->screen0->type)
if(SCREEN_NULL==dev_drv->cur_screen->type)
{
printk(KERN_WARNING "no display device on lcdc%d!?\n",dev_drv->id);
fb_inf->num_lcdc--;
@ -987,25 +1027,25 @@ int rk_fb_register(struct rk_lcdc_device_driver *dev_drv,
fbi->var = def_var;
fbi->fix = def_fix;
sprintf(fbi->fix.id,"fb%d",fb_inf->num_fb);
fbi->var.xres = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->x_res;
fbi->var.yres = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->y_res;
fbi->var.xres = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->x_res;
fbi->var.yres = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->y_res;
fbi->var.grayscale |= (fbi->var.xres<<8) + (fbi->var.yres<<20);
#ifdef CONFIG_LOGO_LINUX_BMP
fbi->var.bits_per_pixel = 32;
#else
fbi->var.bits_per_pixel = 16;
#endif
fbi->var.xres_virtual = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->x_res;
fbi->var.yres_virtual = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->y_res;
fbi->var.width = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->width;
fbi->var.height = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->height;
fbi->var.xres_virtual = fbi->var.xres;
fbi->var.yres_virtual = fbi->var.yres;
fbi->var.width = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->width;
fbi->var.height = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->height;
fbi->var.pixclock = fb_inf->lcdc_dev_drv[lcdc_id]->pixclock;
fbi->var.left_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->left_margin;
fbi->var.right_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->right_margin;
fbi->var.upper_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->upper_margin;
fbi->var.lower_margin = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->lower_margin;
fbi->var.vsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->vsync_len;
fbi->var.hsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->screen0->hsync_len;
fbi->var.left_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->left_margin;
fbi->var.right_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->right_margin;
fbi->var.upper_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->upper_margin;
fbi->var.lower_margin = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->lower_margin;
fbi->var.vsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->vsync_len;
fbi->var.hsync_len = fb_inf->lcdc_dev_drv[lcdc_id]->cur_screen->hsync_len;
fbi->fbops = &fb_ops;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->pseudo_palette = fb_inf->lcdc_dev_drv[lcdc_id]->layer_par[i]->pseudo_pal;

View File

@ -103,6 +103,7 @@ typedef struct rk29fb_screen {
u16 type;
u16 hw_format;
u16 face;
u8 lcdc_id;//which lcdc the screeen connect to
/* Screen size */
u16 x_res;
@ -157,6 +158,10 @@ typedef struct rk29fb_screen {
u8 swap_delta;
u8 swap_dumy;
int xpos; //horizontal display start position on the sceen ,then can be changed by application
int ypos;
int xsize; //horizontal and vertical display size on he screen,they can be changed by application
int ysize;
/* Operation function*/
int (*init)(void);
int (*standby)(u8 enable);