作者:zhenhuaYang | 来源:互联网 | 2023-07-13 18:53
在linux系统中,没有lcd驱动这种叫法,只有framebuffer设备驱动,也就是显存驱动。这种驱动是用于实现提供应用程序的窗口图像的显示接口,如QT窗口程序的显示.struct
在linux系统中,没有lcd驱动这种叫法,只有framebuffer设备驱动,也就是显存驱动。 这种驱动是用于实现提供应用程序的窗口图像的显示接口,如QT窗口程序的显示.
struct fb_info 的一个对象表示一个framebuffer设备
struct fb_info结构体成员比较多, 最起码需要初始化下面列出的几个成员
struct fb_info fbi {
...
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;
__u32 yres;
__u32 xres_virtual;
__u32 yres_virtual;
__u32 bits_per_pixel;
struct fb_bitfield red;
struct fb_bitfield green;
struct fb_bitfield blue;
struct fb_bitfield transp;
unsigned long smem_start;
__u32 smem_len;
__u32 type;
__u32 visual;
__u32 line_length; bit
....
}
///////////////////////所用的函数说明////////////////////
extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
extern void framebuffer_release(struct fb_info *info);
extern int register_framebuffer(struct fb_info *fb_info);
extern int unregister_framebuffer(struct fb_info *fb_info);
void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag)
size指申请多大, dma_handle用来存放物理地址, GFP_KERNEL
函数返回值为申请的缓冲区的虚拟地址
void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle)
释放空间. cpu_addr为虚拟地址, dma_handle为物理地址
在fb_info里的struct fb_ops成员可以为空间,因为基本的操作如fb_open/release/read/write/ioctl等都已在fbmem.c里有实现
同时fb_fillrect函数功能有在cfbfillrect.c里实现,函数名为cfb_fillrect
fb_copyarea 在cfbcopyarea.c
fb_imageblit 在cfbimgblt.c
fb_cursor 在softcursor.c
//////////////////////////////////////////////////
实现一个最简单的fb设备驱动:
test.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>
#define X 1024
#define Y 768
u32 p_addr;
u8 *v_addr;
struct fb_ops fops = {
};
struct fb_info *fbi;
static int __init test_init(void)
{
v_addr = dma_alloc_coherent(NULL, X*Y*4, &p_addr, GFP_KERNEL);
fbi = framebuffer_alloc(100, NULL);
fbi->var.xres = X;
fbi->var.yres = Y;
fbi->var.xres_virtual = X;
fbi->var.yres_virtual = Y;
fbi->var.bits_per_pixel = 32;
fbi->var.red.offset = 16;
fbi->var.red.length = 8;
fbi->var.green.offset = 8;
fbi->var.green.length = 8;
fbi->var.blue.offset = 0;
fbi->var.blue.length = 8;
strcpy(fbi->fix.id, "myfb");
fbi->fix.smem_start = p_addr;
fbi->fix.smem_len = X*Y*4;
fbi->fix.type = FB_TYPE_PACKED_PIXELS;
fbi->fix.visual = FB_VISUAL_TRUECOLOR;
fbi->fix.line_length = X*4;
fbi->fbops = &fops;
fbi->screen_base = v_addr;
fbi->screen_size = X*Y*4;
return register_framebuffer(fbi);
}
static void __exit test_exit(void)
{
unregister_framebuffer(fbi);
framebuffer_release(fbi);
dma_free_coherent(NULL, X*Y*4, v_addr, p_addr);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
//////////////////////////////////
加载模块后,在”/dev/”目录下会多一个fb8设备文件。
可以设置QT的环境变量让QT程序从指定的fb设备刷出来.
如: export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb8
让qt程序执行起来后,再从/dev/fb8读出显存数据,加上图像文件头后,就可以看到QT程序在显存里的状况了