18.4 Linux 帧缓冲设备驱动的模块加载与卸载函数
在帧缓冲设备驱动的模块加载函数中,应该完成如下 4 个工作。
(1)申请 fb_info结构体的内存空间,初始化fb_info结构体中固定和可变的屏幕参数,即填充 fb_info中
struct fb_var_screeninfo var 和 struct fb_fix_screeninfo fix 成员。
(2)根据具体 LCD 屏幕的特点,完成 LCD 控制器硬件的初始化。
(3)申请帧缓冲设备的显示缓冲区空间。
(4)注册帧缓冲设备。
在帧缓冲设备驱动的模块卸载函数中,应该完成相反的工作,包括释放fb_info结构体内存、关闭 LCD、释放显示缓冲区以及注销帧缓冲设备。
由于 LCD 控制器被集成在 SoC 上作为一个独立的硬件模块而存在(成为 platform_device),因此,LCD 驱动中也经常包含平台驱动,这样,在帧缓冲设备驱动的模块加载函数中完成的工作只是注册平台驱动,而初始化 fb_info结构体中的固定和可变参数、LCD 控制器硬件的初始化、申请帧缓冲设备的显示缓冲区空间和注册帧缓冲设备的工作则移交到平台驱动的探测函数中完成。同样地,在使用平台驱动的情况下,释放fb_info结构体内存、关闭 LCD、释放显示缓冲区以及注销帧缓冲设备的工作也移交到平台驱动的移除函数中完成。代码清单18.9所示为帧缓冲设备驱动的模块加载和卸载以及平台驱动的探测和移除函数中的模板。
代码清单 18.9 帧缓冲设备驱动的模块加载/卸载及平台驱动的探测/移除函数的模板
/* 平台驱动探测函数 */
static int _ _init xxxfb_probe(...)
{
struct fb_info *info;
/*分配 fb_info 结构体*/
info = framebuffer_alloc(...);
info->screen_base = framebuffer_virtual_memory;
info->var = xxxfb_var; /* 可变参数 */
info->fix = xxxfb_fix; /* 固定参数 */
/*分配显示缓冲区*/
alloc_dis_buffer(...);
/*初始化 LCD 控制器*/
lcd_init(...);
/*检查可变参数*/
xxxfb_check_var(&info->var, info);
/*注册 fb_info*/
if (register_framebuffer(info) < 0)
return - EINVAL;
return 0;
}
/* 平台驱动移除函数 */
static void _ _exit xxxfb_remove(...)
{
struct fb_info *info = dev_get_drv_data(dev);
if (info) {
unregister_framebuffer(info); /* 注销 fb_info */
dealloc_dis_buffer(...); /* 释放显示缓冲区 */
framebuffer_release(info); /* 注销 fb_info */
}
return 0;
}
/* 平台驱动结构体 */
static struct platform_driver xxxfb_driver = {
.probe = xxxfb_probe,
.remove = xxxfb_remove,
.suspend = xxxfb_suspend,
.resume = xxxfb_resume,
.driver = {
.name = "xxx-lcd", /* 驱动名 */
.owner = THIS_MODULE,
}
};
/* 帧缓冲设备驱动模块加载与卸载函数 */
int __init xxxfb_init(void)
{
return platform_driver_register(&xxxfb_driver); /* 注册平台设备 */
}
static void __exit xxxfb_cleanup(void)
{
platform_driver_unregister(&xxxfb_driver); /* 注销平台设备 */
}
module_init(xxxfb_init);
module_exit(xxxfb_cleanup);