Linux 驱动—LCD学习二:驱动框架(帧缓冲)篇

平台:
Linux :2.6.31
U-Boot:u-boot-2010.06
BusyBox: BusyBox 1.15.2
交叉编译器:arm-linux-v4.3.3

由上到下剖析LCD驱动相关的知识。

1、帧缓冲知识:                                                                                         

帧缓冲设备(frame buffer device)是图像硬件底层之上的一个抽象接口层。它屏蔽底层实现的差异,向上层应用程序提供定义好的、操作硬件的接口(well-defined interface),使得应用程序在图形模式下可以直接对显示缓冲区进行读写。用户在显示缓冲区写入图像数据,图像就会自动在LCD对应区域被显示出来


帧缓冲设备是标准的字符设备,主设备号是29(major 29),次设备号表示不同的帧缓冲号码。

帧缓冲设备通过设备节点进行访问,该节点在/dev目录下,格式是/dev/fbn,n是次设备号,默认取值0~31:

0 = /dev/fb0First frame buffer
      1 = /dev/fb1Second frame buffer
 ...
     31 = /dev/fb31 32nd frame buffer


此外,帧缓冲设备还可以被当做普通的内存设备(memory devices)来访问,可读可写(You can read it, write it, seek to some location in it and mmap() it (the main usage)),比如:

cp /dev/fb0 myfile

2、帧缓冲数据结构和函数:                                                                         

帧缓冲设备的数据结构在内核include/linux/fb.h文件中,关键的有fb_info、fb_ops、fb_var_screeninfo、fb_fix_screeninfo等。相互关系如下图:



fb_info结构体包含了帧缓冲设备的所有属性和操作,具体内容参考源码;

fb_ops结构体包含指向底层操作的函数指针,这些函数需要我们编写;

fb_var_screeninfo结构体包含用户来修改的LCD参数;

fb_fix_screeninfo结构体包含固定的、用户不能修改的参数,当对帧缓冲设备进行映射操作的时候,就从该结构体中取得缓冲区的物理地址。

3、帧缓冲设备的操作实现:                                                                          

帧缓冲设备的实现在/linux/drivers/vedio/fbmem.c文件中,其文件操作结构体如下:

static const struct file_operations fb_fops = {
	.owner =	THIS_MODULE,
	.read =		fb_read,
	.write =	fb_write,
	.unlocked_ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = fb_compat_ioctl,
#endif
	.mmap =		fb_mmap,
	.open =		fb_open,
	.release =	fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
	.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
	.fsync =	fb_deferred_io_fsync,
#endif
};
结构体中的函数在fbmem.c已经实现,没有特殊情况则不需修改。

4、帧缓冲驱动框架:                                                                                        


具体的实现流程是:

s3c2410fb.c实现如下函数并完成封装

static struct fb_ops s3c2410fb_ops = {
	.owner		= THIS_MODULE,
	.fb_check_var	= s3c2410fb_check_var,
	.fb_set_par	= s3c2410fb_set_par,
	.fb_blank	= s3c2410fb_blank,
	.fb_setcolreg	= s3c2410fb_setcolreg,
	.fb_fillrect	= cfb_fillrect,
	.fb_copyarea	= cfb_copyarea,
	.fb_imageblit	= cfb_imageblit,
};

s3c2410fb_ops结构体由函数s3c24xxfb_probe调用:
fbinfo->fbops		    = &s3c2410fb_ops;
s3c24xxfb_probe有函数s3c2410fb_probe调用:
static int __init s3c2410fb_probe(struct platform_device *pdev)
{
	return s3c24xxfb_probe(pdev, DRV_S3C2410);
}
然后s3c2410fb_probe函数被加到平台驱动里面:

static struct platform_driver s3c2412fb_driver = {
	.probe		= s3c2412fb_probe,
	.remove		= s3c2410fb_remove,
	.suspend	= s3c2410fb_suspend,
	.resume		= s3c2410fb_resume,
	.driver		= {
		.name	= "s3c2412-lcd",
		.owner	= THIS_MODULE,
	},
};
最终在函数s3c2410fb_init里面完成驱动的注册:

int __init s3c2410fb_init(void)
{
	int ret = platform_driver_register(&s3c2410fb_driver);

	if (ret == 0)
		ret = platform_driver_register(&s3c2412fb_driver);;

	return ret;
}

注:

如果动态加载的话,执行insmod xxx.ko命令调用module_init并最终由module_init宏进行加载():

module_init(s3c2410fb_init);

参考资料:

[1] linux-2.6.31\Documentation\fb\framebuffer.txt

[2] 宋宝华.Linux 设备驱动开发详解

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值