LCD的核心层:
Fbmem.c (drivers\video)static int __init fbmem_init(void) { proc_create("fb", 0, NULL, &fb_proc_fops); if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) //注册了名字为fb的字符设备,相关操作为fb_fops printk("unable to get major %d for fb devs\n", FB_MAJOR); fb_class = class_create(THIS_MODULE, "graphics");//创建了一个名字为graphics的类 if (IS_ERR(fb_class)) { printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class)); fb_class = NULL; } return 0; }
fb_fops为上层app提供了open,read,write,mmap,ioctrl的相关操作:
open操作:
app: open("/dev/fb0", ...) 主设备号: 29, 次设备号: 0
--------------------------------------------------------------
kernel:
fb_open
int fbidx = iminor(inode);
struct fb_info *info = = registered_fb[0]; // registered_fb很重要,从registered_fb数组中获取到fb_info,并且如果定义了info->fbops->fb_open,就会调用底层的fb_open
read操作:
app: read()
---------------------------------------------------------------
kernel:
fb_read
int fbidx = iminor(inode); //获取次设备号
struct fb_info *info = registered_fb[fbidx]; //和open一样,从registered_fb数组中获取fb_info
if (info->fbops->fb_read) //假如底层定义了info->fbops->fb_read,就使用底层的fb_read
return info->fbops->fb_read(info, buf, count, ppos);
//否则就直接copy_to_user
src = (u32 __iomem *) (info->screen_base + p);
dst = buffer;
*dst++ = fb_readl(src++);
copy_to_user(buf, buffer, c)
int register_framebuffer(struct fb_info *fb_info) { 。。。 fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i); //生成/dev/下的fb节点 。。。 registered_fb[i] = fb_info; //将传进来的fb_info放入到registered_fb数组中 。。。 }
S3cfb.c (drivers\video),可以参考此代码编写驱动程序。
总结一下如何编写一个LCD驱动程序:
1. 分配一个fb_info结构体: framebuffer_alloc
2. 设置,fb_info相关
3. 注册: register_framebuffer
4. 硬件相关的操作:硬件设备寄存器相关
下面是从网上截取的图片,很直观: