概述
LCD驱动是一个标准的platform驱动。当驱动和设备匹配以后,mxsfb_probe 函数就会执行。
mxsfb_probe 函数的主要工作是:
1)、申请fb_info。
framebuffer_alloc()
2)、初始化fb_info结构体中,各个成员变量。
3)、初始化eLCDIF控制器。
4)、使用register_frambebuffer函数向Linux内核注册初始化好的fb_info结构体。
mxsfb_probe 函数中,重要函数/结构体的简要的说明:
1)、
Linux内核将所有的Framebuffer抽象为一个叫fb_info的结构体,fb_info结构体里面包含Framerbuffer设备完整的属性和操作集合,因此,每一个Framebuffer都必须有一个fb_info结构体。换言之,就是lcd驱动,实质上,就是构建fb_info结构体,并且向系统注册fb_info结构体的过程。
struct fb_info {
……
struct fb_var_screeninfo var; /* 当前可变参数 */
struct fb_fix_screeninfo fix; /* 当前固定参数 */
struct fb_ops *fbops; /* 帧缓冲操作函数集 */
char __iomem *screen_base; /* 虚拟内存基地址(屏幕显存) */
unsigned long screen_size; /* 虚拟内存大小(屏幕显存大小) */
void *pseudo_palette; /* 伪 16 位调色板 */
......
};
这个结构体里面的成员变量很多,重要的有如上六个。
2)、register_framebuffer 函数
int register_framebuffer(struct fb_info *fb_info)
3)、mxsfb_probe 函数的主要梳理:
①、
struct mxsfb_info *host;
定义结构体指针变量host,表示IMX6ULL的LCD主控接口,这个结构体是自定义的,里面的成员变量记录了Framebuffer 设备详细信息,比如时钟、 eLCDIF控制器寄存器基地址、 fb_info(struct fb_info *fb_info) 等
②、
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
从设备树中,获取eLCDIF接口控制器的寄存器首地址。寄存器首地址信息,已经在设备树中的,对应的lcd节点中设置了。
lcdif: lcdif@021c8000 {
compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
。。。。。。
};
③、给host、fb_info申请内存
host = devm_kzalloc(&pdev->dev, sizeof(struct mxsfb_info), GFP_KERNEL);
fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
④、通过这一步就将前面申请的 host 和 fb_info 联系在了一起。
host->fb_info = fb_info;
fb_info->par = host;
⑤、对从设备树中获取到的寄存器首地址(res)进行内存映射,得到虚拟地址,并保存到host的base成员变量里面。之后,只要通过访问 host 的 base 成员即可访问 I.MX6ULL 的整个 eLCDIF寄存器。
host->base = devm_ioremap_resource(&pdev->dev, res);
⑥、给pseudo_palette申请内存。
fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,GFP_KERNEL);
⑦、调用 mxsfb_init_fbinfo 函数初始化 fb_info,重点是 fb_info 的 var、 fix、 fbops(操作集),screen_base 和 screen_size。
mxsfb_init_fbinfo(host);
//从设备树中,获取LCD各个参数的信息
-》mxsfb_init_fbinfo_dt(host);
//申请LCD的帧缓冲内存(就是缓存)
-》mxsfb_map_videomem(fb_info)
类似于字符设备操作集file_operations(这里面的函数,已经由芯片厂商写好):
static struct fb_ops mxsfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = mxsfb_check_var,
.fb_set_par = mxsfb_set_par,
.fb_ioctl = mxsfb_ioctl,
.fb_blank = mxsfb_blank,
.fb_pan_display = mxsfb_pan_display,
.fb_mmap = mxsfb_mmap,
……
};
⑧、设置eLCDIF控制器相应的寄存器
mxsfb_set_par(fb_info); //函数里面包含大量的writel()函数
eg:
{ writel(CTRL1_FIFO_CLEAR, host->base + REG_SET);
writel(ctrl, host->base + LCDC_CTRL); …… }
mxsfb_enable_controller(fb_info); //同上(大量的writel())
⑨、调用 register_framebuffer 函数向 Linux 内核注册 fb_info
最后
以上就是辛勤抽屉为你收集整理的LCD驱动中的xxx_probe()函数的全部内容,希望文章能够帮你解决LCD驱动中的xxx_probe()函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复