framebuf驱动分析

分析framebuf的步骤
第一步:
理论分析。          :这一步分的工作。主要是从别人的博客中得来,从鸟哥那本书得来。  
主要是对设备本身的了解程度。

第二步:
应用程序分析。      这一步主要是关于这个设备的应用程序分析,怎么在应用程序中,使用这个设备。










第三步:
进入内核分析,大概分析出 这个体系设计到了那些文件。

分析的结果:
结果1: 这里面那些是内核工作者写的
结果2: 那些需要我们自己添加相应的设备,我们自己驱动工程师需要写的
结果3:  这里设计到那些体系,(比如 输入子系统  I2C系统 platform 等等(这一点需要自己慢慢总结))
/*
分析方法:   经验   makefile make menuconfig 源码 等等 
*/




第四步:深入分析
分为两步:
1.内核工作者写的框架
主要是如何在用户空间调用最终的驱动。这条线  (用户---------->内核 这条线最终调用的)
1.1这里面设计到了那些文件
1.2每个文件具体功能。 他们之间的调用关系
1.3内核工作者,给驱动工程师的接口是什么
2.驱动工程师本
   1.1读懂内核工程师到底给你提供哪些接口,这个接口的作用是什么。-----主要的分析点

1.2读懂别人驱动代码   第一种是架构方面的   另一种是硬件方面的

第五步:达到的层次
1.读懂里面用到的  互斥锁 型号量  读驱动和写驱动时候进行入休眠的状态。

2.重点: 知道数据的生产和消费   数据的来源




第一步分析:这一套体系包含哪些的文件
*************************************
2018.1.13  (一)
*************************************
分析方法:
第一步:经过相关的经验找到 /driver/video这个目录
第二步:在编译过程的源码中找相关的.o文件   




--------- 共有文件
cfbcopyarea.o   --------------cfbcopyarea.c
cfbfillrect.o --------------cfbfillrect.c
cfbimgblt.o --------------cfbimgblt.c
fbcmap.o --------------fbcmap.c
fbcvt.o --------------fbcvt.c
fbmem.o --------------fbmem.c
fbmon.o --------------fbmon.c
fb_notify.o --------------fb_notify.c
fb.o --------------fb.c 
fbsysfs.o --------------fbsysfs.c 
modedb.o ---------------modedb.c 


------------- 操作文件夹   
backlight文件夹下包含的文件    背光的控制  
backlight.o --------- backlight.c  
built-in.o --------- 链接的时候的一些文件
lcd.o --------- lcd.c 
pwm_bl.o --------- pwm_bl.c  



------------- 操作文件夹  
logo文件夹下包含的文件
logo_linux_clut224.o------------ logo_linux_clut224.c
logo_linux_mono.o   ------------ logo_linux_mono.c 
logo_linux_vga16.o ------------ logo_linux_vga16.c 
logo.o ------------ logo.c
logo_x210_clut224.o ------------ logo_x210_clut224.c 




--------------- 操作文件
其他的都是相关的头文件      -------------   这就是相关的驱动工程师所写的
s3cfb_fimd6x.o ---------------------   s3cfb_fimd6x.c  
s3cfb.o ---------------------   s3cfb.c 






第二种分析方法:
第一步:经过相关的经验找到 /driver/video这个目录
第二步:阅读相应的makefile kconfig  make menuconfig 



--------- 共有文件












第二步分析:每一个文件的大致作用。  
这一步分的分析的方法:
第一步:百度上找一块的大致的描述
第二步:理解这个硬件中包含了那些东西
第三步:向别人请教
*************************************
2018.1.13  (二) 
*************************************
第一点:找到主文件:fbmem.c (这个是主要文件) 
主要任务:1、创建graphics类、注册FB的字符设备驱动、提供register_framebuffer接口给具体framebuffer驱动编写着来注册fb设备的。本文件相对于fb来说,
地位和作用和misc.c文件相对于杂散类设备来说一样的,结构和分析方法也是类似的。




第二点:由fb_init_device(fb_info)引出:
/drivers/video/fbsysfs.c文件
主要的作用: 
1.初始化了一些东西
2.在/sys目录下的相关操作
3.创建了相关的设备文件


第三点:由fb_var_to_videomode(&mode, &fb_info->var);引出
/drivers/video/modedb.c 
主要作用是:
模式相关的初始化  
这个文件是管理显示模式(譬如VGA、720P等就是显示模式)的相关与模式库 
//比如分辨率,VGA,刷新率,等等
//主要是这种显示器属于那种模式库


第四点:由fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event)引出
Fb_nitify.c---->notiffer.c这些文件
//管理一个链表  里面添加一些设备驱动 当我们注册一个framebuf之后,
把链表中所有的设备驱动都通知一遍 //反向唤醒机制
//例如:好多人 张三 李四 ....等人,在一家水果店买了很多东西,到货之后,店主给每个人打电话都通知一遍
//framebuf管理通知的 



****************************************************************
驱动工程师需要完成的是那一块
****************************************************************
驱动工程师写的文件
从驱动的角度来看:
drivers\video\samsung\s3cfb.c   这个函数是驱动的主题
static int __devinit s3cfb_probe(struct platform_device *pdev)




s3cfb_fimd6x.c 
这里主要是硬件相关的操作








/****************************************************
第三点细致分析   驱动框架的第一部分  
****************************************************/
分析 /drivers/video/fbmem.c 这个文件  
static int __init fbmem_init(void)
 第一点:
proc_create("fb", 0, NULL, &fb_proc_fops); 
//在proc文件系统中提供了 fb_proc_fops就是在/proc中操作的相关函数  
  
  
 第二点:
register_chrdev(FB_MAJOR,"fb",&fb_fops) //主次设备号




 第三点:
fb_class = class_create(THIS_MODULE, "graphics"); //创建一个graphics这个类


--------------------------------------------------------------------------
fb_fops这个结构体 
static const struct file_operations fb_fops 这个静态结果体
.read
.write 
unlocked_ioctl 
.compat_ioctl
.mmap = fb_mmap,
.open = fb_open,
.release = fb_release,
以read为列 
static ssize_t
fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
//次设备号 用来表示数组的下标
struct fb_info *info = registered_fb[fbidx];
struct fb_info *registered_fb[FB_MAX] __read_mostly;
int num_registered_fb __read_mostly; //告诉你内核已经最多有多少个变量






/****************************************************
第三点细致分析   驱动框架的第二部分 




fb_buf相应的结构体的相关参数
http://www.linuxidc.com/Linux/2012-05/61024.htm
****************************************************/
//注册函数 
int register_framebuffer(struct fb_info *fb_info)
第一点:
检测相关的错误


第二点:
在registered_fb这个数组中找到一个空的结构体
第三点:
fb_info->node = i; 次设备号  
第四点:
fb_info->dev       设备文件 在类下创建设备
第五点:
fb_init_deviece(fb_info) 在sysfs目录下进行相关的处理
第六点:
处理:fb_info->pixmap这个元素  
第七点:
//模式相关的
//struct fb_videomode mode;//模式的名字  //刷新率

fb_var_to_videomode(&mode, &fb_info->var); //作用利用fb_info中var创建一个mode(显示模式)
/*
//驱动把这个mode 产生出来(每一个framebuf都支持不同的mode)
//因此应用层序来消费这个framebuf
//因为这个设备支持好多个显示模式
//驱动的显示模式
设计模式就是说:我当前这个设备
*/






第八步: 唤醒表达机制 
//激活唤醒链表的意思
//阻塞 通知 阻塞通知理论
/*
有九个人在银行排队等待,第一个把事情干完了之后,通知第二个
人,那么后来的人就会向前进一步
对比:你访问一个资源,但是这个资源已经被占用,那么就会被阻塞到这个
资源队列中,当这个资源被激活之后,队列中所有的被阻塞的就在在这个队列中
前进一步

*/


/*
FB_EVENT_FB_REGISTERED 异步通知
(1)表示有的人在关注event(fb注册事件),即告诉内核,当有人注册的
fb的时候,通知一声。如果没有则阻塞在队列中 FB_EVENT_FB_REGISTERED发出的消息机制
有人关注关于fb的所有事件
*/
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);

















************************************************************
驱动部分 2018 1/13(三)
*************************************************************
驱动分析部分 


第一点:设备层  


// \arch\arm\mach-x210.c 
static void __init smdkc110_machine_init(void)
//平台总线的添加
platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));





//   \arch\arm\mach-x210.c 
&s3c_device_fb,

s3cfb_set_platdata(&ek070tn93_fb_data);
//设置了s3cfb_set_platdata(&ek070tn93_fb_data);
s3c_device_fb.dev.platform_data = npd; //最终要打到的效果








//数据的存在 
\arch\arm\plat-s5p\devs.c 

/*
数据 = 信息的描述
*/
struct platform_device s3c_device_fb = {
.name  = "s3cfb",
.id  = -1, //id = -1 系统自己来分配




//num_resources 资源数组
.num_resources  = ARRAY_SIZE(s3cfb_resource),
.resource  = s3cfb_resource,
.dev  = {
.dma_mask = &fb_dma_mask,
.coherent_dma_mask = 0xffffffffUL
// void *platform_data; 在别的地方填充了这个元素
}
};




/*
static 表示限制在当前的文件中
*/
//相应的资源
static struct resource s3cfb_resource[] = {
[0] = {
.start = S5P_PA_LCD,
.end   = S5P_PA_LCD + S5P_SZ_LCD - 1,
.flags = IORESOURCE_MEM, //表示IO操作的内存 寄存器
/*
.flags = IORESOURCE_MEM 表示寄存器
S5P_PA_LCD 表示的LCD寄存器的寄存器首地址
S5P_PA_LCD + S5P_SZ_LCD - 1结束的地址
相似看数据手册


//我们需要物理地址的真正目的是 驱动需要io_reamp成真正的物理
地址
因此驱动是不用写真正的数据  驱动就可以实现真正的紧耦合
*/
},
[1] = {
.start = IRQ_LCD1,
.end   = IRQ_LCD1,
.flags = IORESOURCE_IRQ, //中断号1
},
[2] = {
.start = IRQ_LCD0,
.end   = IRQ_LCD0,
.flags = IORESOURCE_IRQ,//中断号2
},
};




static struct s3c_platform_fb default_fb_data __initdata = {
#if defined(CONFIG_CPU_S5PV210_EVT0)
.hw_ver = 0x60,
#else
.hw_ver = 0x62,
#endif
.nr_wins = 5,
.default_win = CONFIG_FB_S3C_DEFAULT_WINDOW, //2
.swap = FB_SWAP_WORD | FB_SWAP_HWORD,
};


/*
// void *platform_data;  s3cfb_set_platdata
给s3cfb设置platdata  




参数:
//类似于led platform_data  struct s3c_platform_fb 
*/
//smdkc110_machine_init会调用
/*
void *platform_data有好几种,需要用户来配置
因此必须用要用函数来设置
*/
void __init s3cfb_set_platdata(struct s3c_platform_fb *pd)
{
struct s3c_platform_fb *npd;
int i;


if (!pd)
pd = &default_fb_data;//默认的参数


npd = kmemdup(pd, sizeof(struct s3c_platform_fb), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
else {
for (i = 0; i < npd->nr_wins; i++)
npd->nr_buffers[i] = 1;


npd->nr_buffers[npd->default_win] = CONFIG_FB_S3C_NR_BUFFERS;


s3cfb_get_clk_name(npd->clk_name);
npd->clk_on = s3cfb_clk_on;
npd->clk_off = s3cfb_clk_off;


/* starting physical address of memory region */
npd->pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMD, 1);
/* size of memory region */
npd->pmem_size = s5p_get_media_memsize_bank(S5P_MDEV_FIMD, 1);
//最终要的语句
//s3c_device_fb  struct platform_device s3c_device_fb = {上面定义的
s3c_device_fb.dev.platform_data = npd;
}
}






static struct s3c_platform_fb ek070tn93_fb_data __initdata = {
.hw_ver = 0x62,
.nr_wins = 5,  //每一个虚拟窗口
.default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
.swap = FB_SWAP_WORD | FB_SWAP_HWORD,


.lcd = &ek070tn93,
.cfg_gpio = ek070tn93_cfg_gpio,
.backlight_on = ek070tn93_backlight_on,
.backlight_onoff    = ek070tn93_backlight_off,
.reset_lcd = ek070tn93_reset_lcd,
};
//s3c_device_fb.dev.platform_data = npd; 
平台设备的私有数据是s3c_device_fb.dev.platform_data


















/***************************
第二点: s3cfb_probe函数的功能
****************************/
第一步:关键的结构体
 第一点:struct s3c_platform_fb *pdata; //驱动中需要的数据 里面包含了相应的硬件数据和处理方法
 第二点:struct s3cfb_global *fbdev; //硬件需要初始化的数据来源于这个结构体
 第三点:struct resource *res; //资源
/*
struct s3c_platform_fb *pdata = ek070tn93_fb_data  
表示数据的产生 之所以以函数的初始化的方式进行赋值主要的原因:这里pdata有多种可能,需要用户
来进行相关的配置
static struct s3c_platform_fb ek070tn93_fb_data __initdata = {
.hw_ver = 0x62,
.nr_wins = 5,  //每一个虚拟窗口
.default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
.swap = FB_SWAP_WORD | FB_SWAP_HWORD,


.lcd = &ek070tn93,
.cfg_gpio = ek070tn93_cfg_gpio,
.backlight_on = ek070tn93_backlight_on,
.backlight_onoff    = ek070tn93_backlight_off,
.reset_lcd = ek070tn93_reset_lcd,
};
*/


第二步:关键就是数据之间的交换、 把mach-x210.c中的那个platform_device中的那个dev中的
void * data提取出来 也就是ek070tn93_fb_data赋值给pdata
pdata = to_fb_plat(&pdev->dev);


第三步:填充fbdev这个结构体,并且调用了相关初始化的函数
第一点:fbdev->lcd = (struct s3cfb_lcd *)pdata->lcd;
第二点:初始化GPIO
第三点:资源问题
fbdev->regs = ioremap(res->start, res->end - res->start + 1);
第四点:初始化相应的中断
第五点:继续初始化fbdev这个结构体:static int s3cfb_init_global(struct s3cfb_global *ctrl)
第一点显示模式
第二点:设置时钟
第三点:设置分辨率
第四步:设置参数的大小
第六点:进行空间的分配
s3cfb_alloc_framebuffer(fbdev)
第一点:struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);数据间的交换,具体怎么交换看源代码
第二点:ctrl->fb = kmalloc(pdata->nr_wins *sizeof(*(ctrl->fb)), GFP_KERNEL);
第三点:for (i = 0; i < pdata->nr_wins; i++) {
ctrl->fb[i] = framebuffer_alloc(sizeof(*ctrl->fb),ctrl->dev);
总结以上就是为fbdev中的每一个nr_wins分配一个fb_info这样的空间

第四点:s3cfb_init_fbinfo(ctrl, i); 初始化:fbdev中fb_info这个结构体
第七点:进行相关的注册。




第四步:这一步与显示相应的Logo有相应关系
/*
中间很多过程都在进行相关的初始化
*/
//准备窗口 //看这种函数只需要看与我们需求相关的
第一点:fb_prepare_logo( fbdev->fb[pdata->default_win], FB_ROTATE_UR)
fb_find_logo(depth);  //logo.c 


//显示相应的Logo
第二点:fb_show_logo(fbdev->fb[pdata->default_win], FB_ROTATE_UR)
fb_show_logo_line
fb_do_show_logo

info->fbops->fb_imageblit(info, image);最终显示相应的logo

以上都是比较基础分析


还有以下分析:

1.这个驱动动包含了那些文件,每一个文件的作用是什么

2.文件与文件之间是如何调用




















































































































































































/*
//全局变量:
#define FB_MAX 32
struct fb_info *registered_fb[FB_MAX] __read_mostly; //表示一个结构体  起始是一个挂在而已
int num_registered_fb __read_mostly; //告诉内核 内核中已经有多少个framerbuf了
*/












第二步分析:每一个文件的大致作用。  
这一步分的分析的方法:
第一步:百度上找一块的大致的描述
第二步:理解这个硬件中包含了那些东西
第三步:向别人请教




第三步:具体分析
framebuffer驱动框架总览
驱动框架部分
/*
内核驱动工程师写的
*/
(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等就是显示模式)的相关与模式库 
//比如分辨率,VGA,刷新率,等等
//主要是这种显示器属于那种模式库
(4)drivers/video/fb_notify.c 
//管理一个链表  里面添加一些设备驱动 当我们注册一个framebuf之后,
把链表中所有的设备驱动都通知一遍 //反向唤醒机制
//例如:好多人 张三 李四 ....等人,在一家水果店买了很多东西,到货之后,店主给每个人打电话都通知一遍
//framebuf管理通知的 


//驱动框架部分是不涉及具体个人硬件操作的,主要做一些纯软件的东西
//真正的驱动部分在s3cfb.c这一块  
 
5.7.5.2、驱动部+分 //硬件操作
(5)从驱动来看,fb是一个典型的字符设备,而且创建了一个类/sys/class/graphics
(1)drivers/video/samsung/s3cfb.c,驱动主体


(2)drivers/video/samsung/s3cfb_fimd6x.c,里面有很多LCD硬件操作的函数








//devices
(3)arch/arm/mach-s5pv210/mach-x210.c,负责提供platform_device的


2.数据部分
(4)arch/arm/plat-s5p/devs.c,为platform_device提供一些硬件描述信息的





















你可能感兴趣的:(驱动学习)