分析rk代码中fb的加载及逻辑
2015-03-03 17:13
621 查看
fb先于lcdc加载。
fb_probe只是简单的加载一个platform设备fb,并将rk_fb_inf作为fb设备的私有数据。
lcdc设备加载:
根据芯片的配置,RK29中存在两个lcdc设备,分别为lcdc0和lcdc1,通过设备的id来区别。
static struct platform_devicedevice_lcdc0 = {
.name = "rk30-lcdc",
.id = 0,
.num_resources =ARRAY_SIZE(resource_lcdc0),
.resource = resource_lcdc0,
.dev = {
.platform_data = &lcdc0_screen_info,
},
};
static struct platform_devicedevice_lcdc1 = {
.name = "rk30-lcdc",
.id = 1,
.num_resources =ARRAY_SIZE(resource_lcdc1),
.resource = resource_lcdc1,
.dev = {
.platform_data = &lcdc1_screen_info,
},
};
lcdc0用作lcd显示,lcdc1用作hdmi。这些外接设备的控制方式通过lcdc设备的platform_data来设置,并且通过rk29fb_info中的.prop成员制定其中一个设备为主显示设备(primary),另一个为扩展显示设备(extend)
struct rk29fb_info lcdc0_screen_info= {
.prop = PRMRY, //primary display device
.io_init = rk_fb_io_init, //lcd
.io_disable = rk_fb_io_disable,
.io_enable = rk_fb_io_enable,
.set_screen_info = set_lcd_info,
};
struct rk29fb_info lcdc1_screen_info= {
.prop = EXTEND, //extend display device
.lcd_info = NULL,
.set_screen_info = hdmi_init_lcdc, //hdmi
};
其中的set_screen_info是对具体的外接显示设备进行配置。
lcdc设备probe中,rk自己定义了一个设备类型rk30_lcdc_device,rk30_lcdc_device相当于对platform_device的一个扩展,能够根据lcdc的特性,更详细地描述lcdc设备。rk30_lcdc_device中包含了外接设备的控制信息,并且定义了一个rk_screen结构体,这个结构体从screen的角度,描述lcdc对应的显示设备。
lcdc驱动中同时定义了rk30_lcdc_device设备对应的驱动程序rk_lcdc_device_driver。rk_lcdc_device_driver中定义了对lcdc操作的接口,开放给lcdc设备调用。
lcdc驱动中调用rk_fb_register将rk30_lcdc_device和rk_lcdc_device_driver链接起来,将设备注册到fb系统中。在此之前,通过set_screen_info先对外接显示设备进行了初始化。
每个lcdc中可能包含多个layer,目前rk30的lcdc 3个layer,这些信息都是在rk_lcdc_device_driver定义的。
rk_fb_register中,将lcdc的信息添加到rk_fb_inf结构体的lcdc_dev_drv数组成员中,rk_fb_inf最多可以支持4个lcdc。并且初始化lcdc及其各个layer。rk_fb_inf最多支持8个layer。
初始化lcdc之后,系统为lcdc的每个layer分配一个fb_info结构体来保存信息,但是只为lay0层分配buffer。之后为每个layer创建对应的sys操作接口。
以前这些完成后,如果执行rk_fb_register的lcdc是主显示设备(primary),则在此lcdc的外接显示设备上显示开机logo。
此后对于显示的所有操作,都是通过fb完成,fb再通过rk_lcdc_device_driver完成对lcdc的操作。
对应的流程:
fb probe:
static int __devinit rk_fb_probe(struct platform_device *pdev)
{
struct rk_fb_inf *fb_inf = NULL;
//定义一个描述fb信息的数据结构fb_inf
......
fb_inf = kzalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
......
platform_set_drvdata(pdev,fb_inf);
//将fb_inf设备paltform_device的私有数据
......
}
lcdc probe:
static int __devinit rk30_lcdc_probe(struct platform_device *pdev)
{
struct rk30_lcdc_device
*lcdc_dev=NULL; //定义一个rk30_lcdc_device设备
rk_screen *screen;
//定义一个描述screen的数据结构
struct rk29fb_info *screen_ctr_info;
//定义针对外接显示设备控制接口的数据结构
......
platform_set_drvdata(pdev, lcdc_dev);
//将rk30_lcdc_device设为platform_device的私有数据
screen_ctr_info = (structrk29fb_info * )pdev->dev.platform_data;
screen = kzalloc(sizeof(rk_screen), GFP_KERNEL);
......
/****************get lcdc0 reg *************************/
lcdc_dev->id = pdev->id;
res = platform_get_resource(pdev, IORESOURCE_MEM,0);
......
lcdc_dev->reg_phy_base = res->start;
lcdc_dev->len = resource_size(res);
mem =request_mem_region(lcdc_dev->reg_phy_base, resource_size(res),pdev->name);
......
lcdc_dev->reg_vir_base =ioremap(lcdc_dev->reg_phy_base, resource_size(res));
......
lcdc_dev->regs = lcdc_dev->reg_vir_base;
lcdc_dev->regsbak = kzalloc(lcdc_dev->len,GFP_KERNEL);
lcdc_dev->dsp_lut_addr_base = (lcdc_dev->regs +DSP_LUT_ADDR);
lcdc_dev->driver.dev=&pdev->dev;
lcdc_dev->driver.screen0 = screen;
lcdc_dev->driver.cur_screen = screen;
lcdc_dev->driver.screen_ctr_info = screen_ctr_info;
lcdc_dev->irq = platform_get_irq(pdev, 0);
ret = request_irq(lcdc_dev->irq, rk30_lcdc_isr,IRQF_DISABLED,dev_name(&pdev->dev),lcdc_dev);
//以上均为填充rk30_lcdc_device设备的数据
if(screen_ctr_info->set_screen_info)
{
screen_ctr_info->set_screen_info(screen,screen_ctr_info->lcd_info);
if(SCREEN_NULL==screen->type)
{
printk(KERN_WARNING "no display device onlcdc%d!?\n",lcdc_dev->id);
ret = -ENODEV;
}
if(screen_ctr_info->io_init)
screen_ctr_info->io_init(NULL);
} //外接显示设备的初始化
...
ret = rk_fb_register(&(lcdc_dev->driver),&lcdc_driver,lcdc_dev->id);
......
}
static struct layer_par lcdc_layer[] = { //lcdc的三个layer的配置
[0] = {
.name ="win0",
.id = 0,
.support_3d = true,
},
[1] = {
.name ="win1",
.id = 1,
.support_3d = false,
},
[2] = {
.name ="win2",
.id = 2,
.support_3d = false,
},
};
static struct rk_lcdc_device_driverlcdc_driver = {
//定义rk30_lcdc_device设备的驱动driver
.name = "lcdc",
.def_layer_par = lcdc_layer,
.num_layer = ARRAY_SIZE(lcdc_layer),
.open = rk30_lcdc_open,
.init_lcdc = rk30_lcdc_init,
.ioctl = rk30_lcdc_ioctl,
.suspend = rk30_lcdc_early_suspend,
.resume = rk30_lcdc_early_resume,
.set_par =rk30_lcdc_set_par,
.blank =rk30_lcdc_blank,
.pan_display = rk30_lcdc_pan_display,
.load_screen = rk30_load_screen,
.get_layer_state = rk30_lcdc_get_layer_state,
.ovl_mgr = rk30_lcdc_ovl_mgr,
.get_disp_info = rk30_lcdc_get_disp_info,
.fps_mgr = rk30_lcdc_fps_mgr,
.fb_get_layer = rk30_fb_get_layer,
.fb_layer_remap = rk30_fb_layer_remap,
.set_dsp_lut = rk30_set_dsp_lut,
.read_dsp_lut = rk30_read_dsp_lut,
};
上面的rk_fb_register(&(lcdc_dev->driver),&lcdc_driver,lcdc_dev->id)就是讲rk30_lcdc_device与rk_lcdc_device_driver建立连接,将rk30_lcdc_device的driver成员指向rk_lcdc_device_driver。
int rk_fb_register(structrk_lcdc_device_driver *dev_drv,
struct rk_lcdc_device_driver*def_drv,int id)
{
struct rk_fb_inf *fb_inf =platform_get_drvdata(g_fb_pdev);//获取fb描述信息的数据结构
struct fb_info *fbi;
int lcdc_id = 0;
for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++) //可以保存多个lcdc
{
if(NULL==fb_inf->lcdc_dev_drv[i])
{
fb_inf->lcdc_dev_drv[i]= dev_drv;
fb_inf->lcdc_dev_drv[i]->id= id;
fb_inf->num_lcdc++;
break;
}
}
......
lcdc_id = i;
init_lcdc_device_driver(dev_drv,def_drv,id); //将rk_lcdc_device_driver中的api赋给rk30_lcdc_device中对应的操作接口,并对部分数据设置进行初始化.
dev_drv->init_lcdc(dev_drv); //硬件初始化LCDC
/************fb set,one layerone fb ***********/
dev_drv->fb_index_base =fb_inf->num_fb;
for(i=0;i<dev_drv->num_layer;i++) //每个lcdc存在多个layer
{
fbi= framebuffer_alloc(0,&g_fb_pdev->dev); //为每个layer分配一个fb_info
if(!fbi)
{
dev_err(&g_fb_pdev->dev,">>fb framebuffer_alloc fail!");
fbi = NULL;
ret = -ENOMEM;
}
fbi->par = 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]->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->fix.line_length =(fbi->var.xres)*(fbi->var.bits_per_pixel>>3);
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]->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;
if (i == 0) //only allocmemory for main fb
{
rk_request_fb_buffer(fbi,fb_inf->num_fb); //只为layer0分配Buffer
}
ret =register_framebuffer(fbi); //注册到fbmem
if(ret<0)
{
printk("%s>>fb%dregister_framebuffer fail!\n",__func__,fb_inf->num_fb);
ret = -EINVAL;
}
rkfb_create_sysfs(fbi); //创建sys接口
if(i == 0)
{
init_waitqueue_head(&dev_drv->vsync_info.wait);
ret =device_create_file(fbi->dev,&dev_attr_vsync);
if (ret)
{
dev_err(fbi->dev,"failed to create vsync file\n");
}
dev_drv->vsync_info.thread= kthread_run(rk_fb_wait_for_vsync_thread,
dev_drv,"fb-vsync");
if (dev_drv->vsync_info.thread== ERR_PTR(-ENOMEM))
{
dev_err(fbi->dev,"failed to run vsync thread\n");
dev_drv->vsync_info.thread= NULL;
}
dev_drv->vsync_info.active= 1;
}
fb_inf->fb[fb_inf->num_fb]= fbi;
printk("%s>>>>>%s\n",__func__,fb_inf->fb[fb_inf->num_fb]->fix.id);
fb_inf->num_fb++;
}
if(dev_drv->screen_ctr_info->prop == PRMRY) //show logo for primary displaydevice
{
fb_inf->fb[0]->fbops->fb_open(fb_inf->fb[0],1);
fb_inf->fb[0]->fbops->fb_set_par(fb_inf->fb[0]);
if(fb_prepare_logo(fb_inf->fb[0], FB_ROTATE_UR)) {
/* Start display and showlogo on boot */
fb_set_cmap(&fb_inf->fb[0]->cmap, fb_inf->fb[0]);
fb_show_logo(fb_inf->fb[0], FB_ROTATE_UR);
fb_inf->fb[0]->fbops->fb_pan_display(&(fb_inf->fb[0]->var),fb_inf->fb[0]);
}
fb_inf->fb[0]->fbops->fb_ioctl(fb_inf->fb[0],RK_FBIOSET_CONFIG_DONE,NULL);
}
return 0;
}
fb_probe只是简单的加载一个platform设备fb,并将rk_fb_inf作为fb设备的私有数据。
lcdc设备加载:
根据芯片的配置,RK29中存在两个lcdc设备,分别为lcdc0和lcdc1,通过设备的id来区别。
static struct platform_devicedevice_lcdc0 = {
.name = "rk30-lcdc",
.id = 0,
.num_resources =ARRAY_SIZE(resource_lcdc0),
.resource = resource_lcdc0,
.dev = {
.platform_data = &lcdc0_screen_info,
},
};
static struct platform_devicedevice_lcdc1 = {
.name = "rk30-lcdc",
.id = 1,
.num_resources =ARRAY_SIZE(resource_lcdc1),
.resource = resource_lcdc1,
.dev = {
.platform_data = &lcdc1_screen_info,
},
};
lcdc0用作lcd显示,lcdc1用作hdmi。这些外接设备的控制方式通过lcdc设备的platform_data来设置,并且通过rk29fb_info中的.prop成员制定其中一个设备为主显示设备(primary),另一个为扩展显示设备(extend)
struct rk29fb_info lcdc0_screen_info= {
.prop = PRMRY, //primary display device
.io_init = rk_fb_io_init, //lcd
.io_disable = rk_fb_io_disable,
.io_enable = rk_fb_io_enable,
.set_screen_info = set_lcd_info,
};
struct rk29fb_info lcdc1_screen_info= {
.prop = EXTEND, //extend display device
.lcd_info = NULL,
.set_screen_info = hdmi_init_lcdc, //hdmi
};
其中的set_screen_info是对具体的外接显示设备进行配置。
lcdc设备probe中,rk自己定义了一个设备类型rk30_lcdc_device,rk30_lcdc_device相当于对platform_device的一个扩展,能够根据lcdc的特性,更详细地描述lcdc设备。rk30_lcdc_device中包含了外接设备的控制信息,并且定义了一个rk_screen结构体,这个结构体从screen的角度,描述lcdc对应的显示设备。
lcdc驱动中同时定义了rk30_lcdc_device设备对应的驱动程序rk_lcdc_device_driver。rk_lcdc_device_driver中定义了对lcdc操作的接口,开放给lcdc设备调用。
lcdc驱动中调用rk_fb_register将rk30_lcdc_device和rk_lcdc_device_driver链接起来,将设备注册到fb系统中。在此之前,通过set_screen_info先对外接显示设备进行了初始化。
每个lcdc中可能包含多个layer,目前rk30的lcdc 3个layer,这些信息都是在rk_lcdc_device_driver定义的。
rk_fb_register中,将lcdc的信息添加到rk_fb_inf结构体的lcdc_dev_drv数组成员中,rk_fb_inf最多可以支持4个lcdc。并且初始化lcdc及其各个layer。rk_fb_inf最多支持8个layer。
初始化lcdc之后,系统为lcdc的每个layer分配一个fb_info结构体来保存信息,但是只为lay0层分配buffer。之后为每个layer创建对应的sys操作接口。
以前这些完成后,如果执行rk_fb_register的lcdc是主显示设备(primary),则在此lcdc的外接显示设备上显示开机logo。
此后对于显示的所有操作,都是通过fb完成,fb再通过rk_lcdc_device_driver完成对lcdc的操作。
对应的流程:
fb probe:
static int __devinit rk_fb_probe(struct platform_device *pdev)
{
struct rk_fb_inf *fb_inf = NULL;
//定义一个描述fb信息的数据结构fb_inf
......
fb_inf = kzalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
......
platform_set_drvdata(pdev,fb_inf);
//将fb_inf设备paltform_device的私有数据
......
}
lcdc probe:
static int __devinit rk30_lcdc_probe(struct platform_device *pdev)
{
struct rk30_lcdc_device
*lcdc_dev=NULL; //定义一个rk30_lcdc_device设备
rk_screen *screen;
//定义一个描述screen的数据结构
struct rk29fb_info *screen_ctr_info;
//定义针对外接显示设备控制接口的数据结构
......
platform_set_drvdata(pdev, lcdc_dev);
//将rk30_lcdc_device设为platform_device的私有数据
screen_ctr_info = (structrk29fb_info * )pdev->dev.platform_data;
screen = kzalloc(sizeof(rk_screen), GFP_KERNEL);
......
/****************get lcdc0 reg *************************/
lcdc_dev->id = pdev->id;
res = platform_get_resource(pdev, IORESOURCE_MEM,0);
......
lcdc_dev->reg_phy_base = res->start;
lcdc_dev->len = resource_size(res);
mem =request_mem_region(lcdc_dev->reg_phy_base, resource_size(res),pdev->name);
......
lcdc_dev->reg_vir_base =ioremap(lcdc_dev->reg_phy_base, resource_size(res));
......
lcdc_dev->regs = lcdc_dev->reg_vir_base;
lcdc_dev->regsbak = kzalloc(lcdc_dev->len,GFP_KERNEL);
lcdc_dev->dsp_lut_addr_base = (lcdc_dev->regs +DSP_LUT_ADDR);
lcdc_dev->driver.dev=&pdev->dev;
lcdc_dev->driver.screen0 = screen;
lcdc_dev->driver.cur_screen = screen;
lcdc_dev->driver.screen_ctr_info = screen_ctr_info;
lcdc_dev->irq = platform_get_irq(pdev, 0);
ret = request_irq(lcdc_dev->irq, rk30_lcdc_isr,IRQF_DISABLED,dev_name(&pdev->dev),lcdc_dev);
//以上均为填充rk30_lcdc_device设备的数据
if(screen_ctr_info->set_screen_info)
{
screen_ctr_info->set_screen_info(screen,screen_ctr_info->lcd_info);
if(SCREEN_NULL==screen->type)
{
printk(KERN_WARNING "no display device onlcdc%d!?\n",lcdc_dev->id);
ret = -ENODEV;
}
if(screen_ctr_info->io_init)
screen_ctr_info->io_init(NULL);
} //外接显示设备的初始化
...
ret = rk_fb_register(&(lcdc_dev->driver),&lcdc_driver,lcdc_dev->id);
......
}
static struct layer_par lcdc_layer[] = { //lcdc的三个layer的配置
[0] = {
.name ="win0",
.id = 0,
.support_3d = true,
},
[1] = {
.name ="win1",
.id = 1,
.support_3d = false,
},
[2] = {
.name ="win2",
.id = 2,
.support_3d = false,
},
};
static struct rk_lcdc_device_driverlcdc_driver = {
//定义rk30_lcdc_device设备的驱动driver
.name = "lcdc",
.def_layer_par = lcdc_layer,
.num_layer = ARRAY_SIZE(lcdc_layer),
.open = rk30_lcdc_open,
.init_lcdc = rk30_lcdc_init,
.ioctl = rk30_lcdc_ioctl,
.suspend = rk30_lcdc_early_suspend,
.resume = rk30_lcdc_early_resume,
.set_par =rk30_lcdc_set_par,
.blank =rk30_lcdc_blank,
.pan_display = rk30_lcdc_pan_display,
.load_screen = rk30_load_screen,
.get_layer_state = rk30_lcdc_get_layer_state,
.ovl_mgr = rk30_lcdc_ovl_mgr,
.get_disp_info = rk30_lcdc_get_disp_info,
.fps_mgr = rk30_lcdc_fps_mgr,
.fb_get_layer = rk30_fb_get_layer,
.fb_layer_remap = rk30_fb_layer_remap,
.set_dsp_lut = rk30_set_dsp_lut,
.read_dsp_lut = rk30_read_dsp_lut,
};
上面的rk_fb_register(&(lcdc_dev->driver),&lcdc_driver,lcdc_dev->id)就是讲rk30_lcdc_device与rk_lcdc_device_driver建立连接,将rk30_lcdc_device的driver成员指向rk_lcdc_device_driver。
int rk_fb_register(structrk_lcdc_device_driver *dev_drv,
struct rk_lcdc_device_driver*def_drv,int id)
{
struct rk_fb_inf *fb_inf =platform_get_drvdata(g_fb_pdev);//获取fb描述信息的数据结构
struct fb_info *fbi;
int lcdc_id = 0;
for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++) //可以保存多个lcdc
{
if(NULL==fb_inf->lcdc_dev_drv[i])
{
fb_inf->lcdc_dev_drv[i]= dev_drv;
fb_inf->lcdc_dev_drv[i]->id= id;
fb_inf->num_lcdc++;
break;
}
}
......
lcdc_id = i;
init_lcdc_device_driver(dev_drv,def_drv,id); //将rk_lcdc_device_driver中的api赋给rk30_lcdc_device中对应的操作接口,并对部分数据设置进行初始化.
dev_drv->init_lcdc(dev_drv); //硬件初始化LCDC
/************fb set,one layerone fb ***********/
dev_drv->fb_index_base =fb_inf->num_fb;
for(i=0;i<dev_drv->num_layer;i++) //每个lcdc存在多个layer
{
fbi= framebuffer_alloc(0,&g_fb_pdev->dev); //为每个layer分配一个fb_info
if(!fbi)
{
dev_err(&g_fb_pdev->dev,">>fb framebuffer_alloc fail!");
fbi = NULL;
ret = -ENOMEM;
}
fbi->par = 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]->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->fix.line_length =(fbi->var.xres)*(fbi->var.bits_per_pixel>>3);
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]->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;
if (i == 0) //only allocmemory for main fb
{
rk_request_fb_buffer(fbi,fb_inf->num_fb); //只为layer0分配Buffer
}
ret =register_framebuffer(fbi); //注册到fbmem
if(ret<0)
{
printk("%s>>fb%dregister_framebuffer fail!\n",__func__,fb_inf->num_fb);
ret = -EINVAL;
}
rkfb_create_sysfs(fbi); //创建sys接口
if(i == 0)
{
init_waitqueue_head(&dev_drv->vsync_info.wait);
ret =device_create_file(fbi->dev,&dev_attr_vsync);
if (ret)
{
dev_err(fbi->dev,"failed to create vsync file\n");
}
dev_drv->vsync_info.thread= kthread_run(rk_fb_wait_for_vsync_thread,
dev_drv,"fb-vsync");
if (dev_drv->vsync_info.thread== ERR_PTR(-ENOMEM))
{
dev_err(fbi->dev,"failed to run vsync thread\n");
dev_drv->vsync_info.thread= NULL;
}
dev_drv->vsync_info.active= 1;
}
fb_inf->fb[fb_inf->num_fb]= fbi;
printk("%s>>>>>%s\n",__func__,fb_inf->fb[fb_inf->num_fb]->fix.id);
fb_inf->num_fb++;
}
if(dev_drv->screen_ctr_info->prop == PRMRY) //show logo for primary displaydevice
{
fb_inf->fb[0]->fbops->fb_open(fb_inf->fb[0],1);
fb_inf->fb[0]->fbops->fb_set_par(fb_inf->fb[0]);
if(fb_prepare_logo(fb_inf->fb[0], FB_ROTATE_UR)) {
/* Start display and showlogo on boot */
fb_set_cmap(&fb_inf->fb[0]->cmap, fb_inf->fb[0]);
fb_show_logo(fb_inf->fb[0], FB_ROTATE_UR);
fb_inf->fb[0]->fbops->fb_pan_display(&(fb_inf->fb[0]->var),fb_inf->fb[0]);
}
fb_inf->fb[0]->fbops->fb_ioctl(fb_inf->fb[0],RK_FBIOSET_CONFIG_DONE,NULL);
}
return 0;
}
相关文章推荐
- [原创]Android Lollipop (5.0) 原生代码 Settings 首页加载逻辑分析
- Android Lollipop (5.0) 原生代码 Settings 首页加载逻辑分析
- GstBin和sink组件的状态转换代码分析和相关逻辑
- PMON中autoload自动加载操作系统代码分析
- hazelcast客户端连接和操作代码逻辑分析
- hadoop核心逻辑shuffle代码分析-reduce端
- hadoop核心逻辑shuffle代码分析-map端
- 分析代码中的业务逻辑是程序员的必经之路
- 【Nutch2.2.1源代码分析之4】Nutch加载配置文件的方法 分类: H3_NUTCH 2014-08-22 21:57 928人阅读 评论(0) 收藏
- FFMPeg代码分析:AVCodec结构体以及编解码器的查找和加载
- 开源代码分析技巧之——打印调用逻辑
- hadoop核心逻辑shuffle代码分析-map端
- JME基础教程代码分析9 碰撞、刚体、场景加载
- hadoop核心逻辑shuffle代码分析-reduce端
- hadoop核心逻辑shuffle代码分析-map端
- FFMPeg代码分析:AVCodec结构体以及编解码器的查找和加载
- OSChina Android源代码剖析(5)—首页代码逻辑分析之广播接收器
- hadoop核心逻辑shuffle代码分析-map端
- VLC plugin加载代码分析
- JD-GUI反编译后代码逻辑分析