init部分主要完成的任务是:屏的初始化,显示的初始化,最后打开lcd,背光,等待图片数据输入,然后输出。(产生fbinfo结构体给fbmem.c使用)
用户操作的流程包括:ioctl控制图片的显示属性(读取初始化时的配置或者使用bsp操作寄存器改变显示设置)和显示图片的数据源。(概括说就是控制和数据两条线)
这一节主要分析init部分,就是属于***fb.c文件的函数。
驱动程序绑定由内核自动执行,当内核发现一个驱动程序与一个设备匹配时,将调用驱动程序的probe函数,完成对设备的探测及初始化等工作。device与driver是用名字搭配的,其实注册并部分先后,device注册时会去找driver,driver注册的时候会去找device,当配对成功后,driver就从device中获取必要的数据(使用到资源或者一些参数),然后对设备进行初始化。搭建必要的设备运行环境,比如lcd需要在内存中申请一段空间,用于接收用户发送过来的数据。只有都准备完毕了,才可以打开设备,等待用户操作。(lcd driver还产生了一个结构体fbinfo,存放了用户可能用到的所有信息,放到fbmem.c中)这样probe函数的入口参数就可以解释了。
kzalloc
用kzalloc申请内存的时候, 效果等同于先是用 kmalloc() 申请空间 , 然后用 memset() 来初始化 ,所有申请的元素都被初始化为 0.
首先为什么要使用这个函数,目的是在堆空间分配一段内存给一个指针,然后初始化为0。其实完成同样的功能也可以这样,先定义一个结构体实例,并初始化为0,然后把这个对象赋值给那个指针。结果都是一个指针指向了一段大小一样空的内存,只不过一个在堆,一个在栈。不过在堆中更容易控制,可以自己free掉,而不需要等待系统去帮你free。有个不好就是把指针给别人用,别人却不去free它,那就糟了,这一点还是比不上结构体实例的。
platform_get_resource
struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num) { int i; for (i = 0; i < dev->num_resources; i++) {
//不管你想找哪一类资源,都要从第一个资源看是比对,所以效率吗貌似有点低,不过一般总资源数也不多。 struct resource *r = &dev->resource[i]; if (type == resource_type(r) && num-- == 0) return r;
//找到匹配的之后把整个结构体返回。 } return NULL;
//没找到就返回空。 }
//这里取出的资源包括中断号,io端口的寄存器物理地址等。这些资源是设备需要用的,驱动取出后用于静态申请(就是已知物理地址,中断号的情况下去申请物理地址和中断号),可以理解为,
//告诉系统这段物理地址和中断号被占用,不能再分配给其他设备了。如果没有lcd,这些资源就可以给别人用了。这些都是系统资源啊,大家共用的。
info->mem = request_mem_region(res->start, resource_size(res), pdev->name);
//这就是申请指定的io物理地址空间,告诉系统,这段物理地址被lcd占用。(后来使用寄存器的物理地址) info->io = ioremap(res->start, resource_size(res));
//把申请到的物理地址空间映射到虚拟地址空间中,后来操作寄存器都是使用的虚拟地址。
framebuffer_alloc()
framebuffer_alloc()功能是向内核申请一段大小为sizeof(struct fb_info) + size的空间,其中size的大小代表设备的私有数据空间,并用fb_info的par域指向该私有空间。为什要价size大小,因为这样才是整个fbinfo的大小,私有数据空间需要与fbinfo一起free,就是说这段数据是不可缺少的,那么为什么不用结构体来存放,这样与fbinfo就是一个整体了啊,一起free更有说服力。大家注意一下par是个void型的指针,为什么要是void型的呢,因为他自己都不知道他将要指向的私有数据类型,那你用什么结构体来存放这莫名的私有数据呢。fbinfo这个结构体里面的成员是定好的,他是与fbmem.c的接口,这个接口结构体中就只有这样一个私有数据指针是可变的,是给用户发挥的。这就解释了为什么par是void类型的指针。既然fbinfo是在***fb.c中申请的,作为数据接口给fbmem.c,那么在init结束后也是不能释放的,所以放在堆里面很安全,在注销驱动的时候在remove函数内会free掉,很方便是不是?
关于android lcd doublebuffer问题
DMA从SDRAM FIFO中取数据,送给显存buffer的时候,中间需要进行处理,比如mix alphableeding,colorkey等工作,这些时间并不长,但是在进行处理时,SDRAM FIFO中的数据无法更新,可以理解为是基于此FIFO进行合成等工作的,合成完了才会送到显存FIFO,送完后等待取出下一张要显示的图片,取图片又是需要时间的,两个时间加起来就无法忽略了,有明显的延迟。所以使用doublebuffer,就是行为原来的两倍,可以存两张图片,一个用来合成,一个用来绘制,两个交替使用,解决延迟的问题。(这也就是通常说的pan_display)