第一部分 framebuffer 概念介绍
1、framebuffer帧缓冲
帧缓冲(framebuffer)是Linux系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都是由帧缓冲设备驱动本身来完成。
framebuffer机制模仿显卡的功能,将显卡硬件结构抽象为一系列的数据结构,可以通过对framebuffer的读写直接对显存进行操作。用户可以将framebuffer看成是显卡的一个映像,将其映射到进程空间后,就可以直接读写操作,写操作会直接反映在屏幕上。
framebuffer是一个字符设备,主设备号是29,对应于/dev/fb%d设备文件。通常,使用如下方式(数字代表次设备号)
0 = /dev/fb0 第一个fb设备
1 = /dev/fb1 第二个fb设备
fb也是一种普通的内存设备,可以读写其内容。例如,屏幕抓屏:cp /dev/fb0 myfilefb 虽然可以向内存设备(/dev/mem)一样,对其read、write、seek以及mmap。但区别在于fb使用的不是整个内存区。而是显存部分。
2、fb与应用程序的互交
对于应用程序而言,它和其它的设备并没有什么区别,用户可以把fb看成是一块内存,既可以向内存中写数据,也可以读数据。fb的显示缓冲区位于内核空间。应用程序可以把此空间映射到自己的用户空间,再进行操作。
在应用程序中,操作/dev/fbn的一般步骤如下:
(1)打开/dev/fbn设备文件。
(2)用ioctl()操作取得当前显示屏幕的参数,如屏幕的分辨率、每个像素点的比特数。根据屏幕的参数可计算屏幕缓冲区的大小。
(3)用mmap()函数,将屏幕缓冲区映射到用户空间。
(4)映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示。
第二部分 framebuffer数据结构分析
framebuffer涉及的数据结构如下:
(1)struct fb_info
一个帧缓冲区对应一个struct fb_info结构,它包括了帧缓冲设备的属性和操作的完整集合,每个帧设备都有一个fb_info结构体。
(2)struct fb_ops
结构体用来实现对帧缓冲设备的操作,这些函数需要驱动开发人员编写,
(3)struct fb_fix_screeninfo
该结构体记录了用户不能修改的固定显示控制器参数。这些固定的参数如缓冲区的物理地址、缓冲区的长度等等。
(4)struct fb_var_screeninfo
结构体中存储了用户可以修改的显示器控制参数,例如屏幕分辨率、透明度等等。
(5)struct fb_cmap
结构体中记录了颜色板信息,即调色板信息。,用户空间可以通过ioctl()的FBIOGETCMAP和 FBIOPUTCMAP命令读取或设定颜色表。
以上结构体的关系如下:
(6)struct fb_bitfield
结构体描述每一像素显示缓冲区的组织方式,包含位域偏移、位域长度和MSB 指示。
第三部分 framebuffer核心层框架分析
framebuffer设备在Linux中是以平台设备形式存在的,fb设备驱动核心层为上层提供了系统调用,为底层驱动提供了接口,核心层的主文件及其功能如下。
(1)drivers/video/fbmem.c。主要任务:1、创建graphics类、注册FB的字符设备驱动、提供register_framebuffer接口给具体framebuffer驱动编写着来注册fb设备的。本文件相对于fb来说,地位和作用和misc.c文件相对于杂散类设备来说一样的,结构和分析方法也是类似的。
(2)drivers/video/fbsys.c。这个文件是处理fb在/sys目录下的一些属性文件的。
(3)drivers/video/modedb.c。这个文件是管理显示模式(譬如VGA、720P等就是显示模式)的
(4)drivers/video/fb_notify.c
fbmem_init函数
(1)#ifdef MODULE
(2)fb_proc_fops和fb在proc文件系统中的表现
(3)register_chrdev注册fb设备
(4)class_create创建graphics类
(5)fbmem_exit的对应
fb_fops
(1)为应用层实现read/write/mmap/ioctl在驱动层的接口
(2)registered_fb和num_registered_fb
(3)struct fb_info register_framebuffer函数
(1)fb驱动框架开放给驱动编写着的注册接口
(2)fb_check_foreignness
(3)remove_conflicting_framebuffers
(4)device_create
(5)fb_init_device
fb在sysfs中的接口
(1)device_attrs
(2)dev_set_drvdata和dev_get_drvdata
注册登记该fb设备
(1)registered_fb[i] = fb_info;
(2)结合fb_read等函数中对fb_info的使用
(3)关键点:数据如何封装、数据由谁准备由谁消费、数据如何传递
第四部分 framebuffer驱动层分析
驱动层涉及源码文件:
(1)drivers/video/samsung/s3cfb.c,驱动主体,主要是处理和数据结构有关的
(2)drivers/video/samsung/s3cfb_fimd6x.c,里面有很多LCD硬件操作的函数,主要是处理和硬件有关的
(2)arch/arm/mach-s5pv210/mach-x210.c,负责提供platform_device的
(3)arch/arm/plat-s5p/devs.c,为platform_device提供一些硬件描述信息
s3cfb.c文件probe函数分析
(1)struct s3c_platform_fb *pdata;
struct s3c_platform_fb 这个结构体是fb的platform_data结构体,这个结构体变量就是platform设备的私有数据,这个数据在platform_device.device.platform_data中存储。在mach文件中去准备并填充这些数据,在probe函数中通过传参的platform_device指针取出来。
(2)struct s3cfb_global 这个结构体主要作用是在驱动部分的2个文件(s3cfb.c和s3cfb_fimd6x.c)的函数中做数据传递用的。
(3)struct resource
(4)regulator
mach-x210.c文件分析
smdkc110_machine_init函数里面主要是做了一些该平台下数据的初始化,里面涉及fb的由两个部分,如下:
(1)platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices)); //存放平台数据
smdkc110_devices
s3c_device_fb
(2)s3cfb_set_platdata(&ek070tn93_fb_data); //主要是用于提供设置GPIO的函数
第五部分 修改内核logo
1、找一个需要显示的logo的png格式的图片(图片分辨率不得大于屏幕分辨率),并将其命令为logo.png
2、在终端下执行以下命令
pngtopnm logo.png | ppmquant -fs 224 | pnmtoplainpnm > logo_linux_clut224.ppm
3、将生成的ppm文件拷贝到替换掉/root/porting_x210/kernel/x210kernel/drivers/video/logo/目录下
并将其改名为logo_x210_clut224.ppm
4、make
备注:
(1)修改fbmem.c的471行可以修改Logo显示的位置,例如,显示在屏幕中间:
image.dx = (info->var.xres - logo->width)/2;
image.dy = (info->var.yres - logo->height)/2;
(2)如果图片显示不出来可能有以下原因
a、内核里framebuffer的分辨率不对,可以在mach-x210.c的225行修改(1024 * 600);
b、只能在左上角显示,CONFIG_FRAMEBUFFER_CONSOLE宏可能被选中(该宏不需要勾选,可以现在.config里面查看,确定后,make menuconfig 去除)