Frambuff基础

FrameBuffer(帧缓冲) 的原理
FrameBuffer 是出现在 Linux内核当中的一种驱动程序接口。它是Linux内核抽象出来的设备,供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由Framebuffer设备驱动来完成的。但Framebuffer本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池.CPU将运算后的结果放到这个水池,水池再将结果流到显示器.中间不会对数据做处理. 应用程序也可以直接读写这个水池的内容.在这种机制下,尽管Framebuffer需要真正的显卡驱动的支持,但所有显示任务都有CPU完成,因此CPU负担很重。



 1、struct fb_info数据结构(FBI)

 FBI 中记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及操作函数指针。每一个帧缓冲设备都必须对应一个 FBI。

1 struct fb_info   

2  {   
3     int node;   
4     int flags;   
5     struct fb_var_screeninfo var; /*可变参数 */   
6     struct fb_fix_screeninfo fix; /*固定参数 */   
7     struct fb_monspecs monspecs; /*显示器标准 */   
8     struct work_struct queue; /* 帧缓冲事件队列 */   
9     struct fb_pixmap pixmap; /* 图像硬件mapper */   
10    struct fb_pixmap sprite; /* 光标硬件mapper */   
11    struct fb_cmap cmap; /* 目前的颜色表*/   
12    struct list_head modelist;    
13    struct fb_videomode *mode; /* 目前的video模式 */   
14    
15    #ifdef CONFIG_FB_BACKLIGHT   
16       struct mutex bl_mutex;   
17       /* 对应的背光设备  */   
18       struct backlight_device *bl_dev;   
19       /* 背光调整 */   
20       u8 bl_curve[FB_BACKLIGHT_LEVELS];   
21     #endif   
22    
23     struct fb_ops *fbops; /* fb_ops,帧缓冲操作 */   
24     struct device *device;   
25     struct class_device *class_device; /   
26     int class_flag; /* 私有sysfs标志 */   
27     #ifdef CONFIG_FB_TILEBLITTING   
28         struct fb_tile_ops *tileops; /* 图块Blitting */   
29     #endif   
30     char _  _iomem *screen_base; /* 虚拟基地址 */   
31     unsigned long screen_size; /* ioremapped的虚拟内存大小 */   
32     void *pseudo_palette; /* 伪16色颜色表 */   
33     #define FBINFO_STATE_RUNNING  0   
34     #define FBINFO_STATE_SUSPENDED         1   
35     u32 state; /* 硬件状态,如挂起 */   
36     void *fbcon_par;   
37     void *par;   

38 };   



2 fb_ops结构体 
FBI 的成员变量 fb_ops 为指向底层操作的函数的指针,这些函数是需要驱动程序开发人员编写的。
1 struct fb_ops   
2  {   
3      struct module *owner;   
4       /* 打开/释放 */   
5      int(*fb_open)(struct fb_info *info, int user);   
6      int(*fb_release)(struct fb_info *info, int user);   
7     
8      /* 对于非线性布局的/常规内存映射无法工作的帧缓冲设备需要 */   
9      ssize_t(*fb_read)(struct file *file, char _  _user *buf, size_t  
count,   
10        loff_t*ppos);   
11     ssize_t(*fb_write)(struct file *file, const char _  _user *buf,  
size_t count,   
12        loff_t *ppos);   
13    
14     /* 检测可变参数,并调整到支持的值*/   
15         int(*fb_check_var)(struct  fb_var_screeninfo  *var,  struct  
fb_info *info);   
16    
17    /* 根据info->var设置video模式 */
int(*fb_set_par)(struct fb_info *info);   
19    
20    /* 设置color寄存器 */   
21    int(*fb_setcolreg)(unsigned  regno,  unsigned  red,  unsigned  green,   
unsigned   
22        blue, unsigned transp, struct fb_info *info);   
23    
24     /* 批量设置color寄存器,设置颜色表 */   
25     int(*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);   
26    
27     /*显示空白 */   
28     int(*fb_blank)(int blank, struct fb_info *info);   
29    
30     /* pan显示 */   
31      int(*fb_pan_display)(struct  fb_var_screeninfo  *var,  struct   
fb_info *info);   
32    
33     /* 矩形填充 */   
34        void(*fb_fillrect)(struct  fb_info  *info,  const  struct  
fb_fillrect *rect);   
35     /* 数据复制 */   
36        void(*fb_copyarea)(struct  fb_info  *info,  const  struct  
fb_copyarea *region);   
37     /* 图形填充 */   
38     void(*fb_imageblit)(struct  fb_info  *info,  const  struct  fb_image  
*image);   
39    
40     /* 绘制光标 */   
41     int(*fb_cursor)(struct  fb_info  *info,  struct  fb_cursor  *cursor);  
42    
43     /* 旋转显示 */   
44     void(*fb_rotate)(struct fb_info *info, int angle);   
45    
46     /* 等待blit空闲 (可选) */   
47     int(*fb_sync)(struct fb_info *info);   
48    
49     /* fb特定的ioctl (可选) */   
50   int(*fb_ioctl)(struct  fb_info *info,  unsigned int  cmd, unsigned  
long arg);   
51    
52   /* 处理32位的compat ioctl (可选) */   
53     int(*fb_compat_ioctl)(struct  fb_info  *info,  unsigned  cmd,  
unsigned long arg);   
54    
55   /* fb特定的mmap */   
56   int(*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);  
57    
58   /* 保存目前的硬件状态 */   
59   void(*fb_save_state)(struct fb_info *info);   
60    
61   /* 恢复被保存的硬件状态 */   
62   void(*fb_restore_state)(struct fb_info *info);   
63 };   



Linux Frame Buffer 驱动程序层次结构
Frame Buffer 设备驱动可以从三个层次来看:
应用程序与系统调用;
适用于所有设备的通用代码,避免重复,包括 file_operations 结构、register/unregister framebuffer 接口等;
操作具体硬件的代码,主要是 fb_ops 结构。

在 Linux 内核中,Frame Buffer 设备驱动的源码主要在以下两个文件中,它们处于 frame buffer 驱动体系结构的中间层,它为上层的用户程序提供系统调用,也为底层特定硬件驱动提供了接口:
linux/inlcude/fb.h
linux/drivers/video/fbmem.c
数据结构
头文件 fb.h 定义了所有的数据结构:
fb_var_screeninfo:描述了一种显卡显示模式的所有信息,如宽、高、颜色深度等,不同的显示模式对应不同的信息;
fb_fix_screeninfo:定义了显卡信息,如 framebuffer 内存的起始地址,地址长度等;
fb_cmap:设备独立的 colormap 信息,可以通过 ioctl 的 FBIOGETCMAP 和 FBIOPUTCMAP 命令设置 colormap;
fb_info:包含当前 video card 的状态信息,只有 fb_info 对内核可见;
fb_ops : 应用程序使用 ioctl 系统调用操作底层的 LCD 硬件,fb_ops 结构中定义的方法用于支持这些操作;






在mach-smdk2410.c中,定义了初始的LCD参数。注意这是个全局变量。
static struct s3c2410fb_mach_info smdk2410_lcd_cfg = {
 .regs= {
  .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
   S3C2410_LCDCON1_TFT|
   S3C2410_LCDCON1_CLKVAL(7),
  ......
 },
 .width  = 240,   .height = 320,
 .xres = {.min = 240,.max= 240,.defval = 240},
 .bpp   = {.min = 16,  .max= 16,  .defval = 16},
 ......
};
(2)内核初始化时候调用s3c2410fb_probe函数。下面分析这个函数的做的工作。首先先动态分配s3c2410fb_info空间。
   fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info),&pdev->dev);
把域mach_info指向mach-smdk2410.c中的smdk2410_lcd_cfg 。
info->mach_info = pdev->dev.platform_data;
设置fb_info域的fix,var,fops字段。

fbinfo->fix.type  =  FB_TYPE_PACKED_PIXELS;
fbinfo->fix.type_aux     = 0;
fbinfo->fix.xpanstep     = 0;

fbinfo->var.nonstd     = 0;
fbinfo->var.activate   = FB_ACTIVATE_NOW;
fbinfo->var.height     = mach_info->height;
fbinfo->var.width     = mach_info->width;

fbinfo->fbops      = &s3c2410fb_ops;
……
该函数调用s3c2410fb_map_video_memory()申请DMA内存,即显存。

fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);
fbi->map_cpu  = dma_alloc_writecombine(fbi->dev, fbi->map_size,
          &fbi->map_dma, GFP_KERNEL);

fbi->map_size = fbi->fb->fix.smem_len;
…….
设置控制寄存器,设置硬件寄存器。

memcpy(&info->regs, &mach_info->regs,sizeof(info->regs));
info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
……….
调用函数s3c2410fb_init_registers(),把初始值写入寄存器。

writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
   writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);

(3)当用户调用mmap()映射内存的时候,Fbmem.c把刚才设置好的显存区域映射给用户。
  start = info->fix.smem_start;
  len = PAGE_ALIGN( (start & ~PAGE_MASK) + info->fix.smem_len);
  io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,vma->vm_page_prot);
  ……
这样就完成了驱动初始化到用户调用的整个过程。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值