偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.
全部博文(1748)
分类: LINUX
2010-11-15 08:59:26
|
|
|
|
1. 帧缓冲设备驱动在Linux子系统中的结构如下:
我
们从上面这幅图看,帧缓冲设备在Linux中也可以看做是一个完整的子系统,大体由fbmem.c和xxxfb.c组成。向上给应用程序提供完善的设备文
件操作接口(即对FrameBuffer设备进行read、write、ioctl等操作),接口在Linux提供的fbmem.c文件中实现;向下提供
了硬件操作的接口,只是这些接口Linux并没有提供实现,因为这要根据具体的LCD控制器硬件进行设置,所以这就是我们要做的事情了(即xxxfb.c
部分的实现)。
2. 帧缓冲相关的重要数据结构:
从
帧缓冲设备驱动程序结构看,该驱动主要跟fb_info结构体有关,该结构体记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及对底层硬件操作的
函数指针。在Linux
中,每一个帧缓冲设备都必须对应一个fb_info,fb_info在/linux/fb.h中的定义如下:(只列出重要的一些)
|
其中,比较重要的成员有struct fb_var_screeninfo var、struct fb_fix_screeninfo fix和struct fb_ops * fbops,他们也都是结构体。下面我们一个一个的来看。
fb_var_screeninfo结构体主要记录用户可以修改的控制器的参数,比如屏幕的分辨率和每个像素的比特数等,该结构体定义如下:
|
而fb_fix_screeninfo结构体又主要记录用户不可以修改的控制器的参数,比如屏幕缓冲区的物理地址和长度等,该结构体的定义如下:
|
fb_ops结构体是对底层硬件操作的函数指针,该结构体中定义了对硬件的操作有:(这里只列出了常用的操作)
|
3. 帧缓冲设备作为平台设备:
在S3C2440中,LCD控制器被集成在芯片的内部作为一个相对独立的单元,所以Linux把它看做是一个平台设备,故在内核代码/arch/arm/plat-s3c24xx/devs.c 中定义有LCD相关的平台设备及资源,代码如下:
|
*/ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
|
从 上面的代码来看,要使LCD控制器支持其他的LCD屏,重要的是根据LCD的数据手册修改以上这些参数的值。下面,我们再看一下在驱动中是如果引用到 s3c2410fb_mach_info结构体的(注意上面讲的是在内核中如何使用的)。在mach-smdk2440.c中有:
|
s3c24xx_fb_set_platdata定义在 plat-s3c24xx/devs.c中:
|
最后:当编译好内核烧到目标板上时,屏闪比较厉害,通过查看屏的datasheet 得知,屏的时钟频率为33MHz,通过工式计算出clkdiv 值为0,最接近lcd 的时钟频率。文件是:drivers/video/s3c2440fb.c
clkdiv= 2;
if (type == S3C2410_LCDCON1_TFT) {
s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);
--clkdiv;
if (clkdiv < 0)
clkdiv = 0;
} else {
s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);
if (clkdiv < 2)
clkdiv = 2;
}
添加如下代码:clkdiv = 0;
屏不闪了。
这 里再讲一个小知识:不知大家有没有留意,在平台设备驱动中,platform_data可以保存各自平台设备实例的数据,但这些数据的类型都是不同的,为 什么都可以保存?这就要看看platform_data的定义,定义在/linux/device.h中,void *platform_data是一个void类型的指针,在Linux中void可保存任何指针的数据类型。
原文地址 http://blog.csdn.net/control_tech/archive/2010/06/30/5705344.aspx