framebuffer帧缓冲(简称fb)是linux内核中虚拟出的一个设备,framebuffer向应用层提供一个统一标准接口的显示设备,从驱动来看,fb是一个典型的字符设备,而且创建了一个类/sys/class/graphics
,设备文件 /dev/fb0
在应用层中如果要使用的话需要包含头文件 #include <linux/fb.h>
然后使用mmap做映射
1、核心层的代码fbmem.c
这个代码是内核实现的,我们只是分析一下,并不需要我们去做什么改动
① 入口函数fbmem_init:
fbmem_init(void)
{
create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);
if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
printk("unable to get major %d for fb devs\n", FB_MAJOR);
fb_class = class_create(THIS_MODULE, "graphics");
if (IS_ERR(fb_class)) {
printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
fb_class = NULL;
}
return 0;
}
fbmem_init里面注册字符设备fb,其主设备号为29.并且创建了类class_create,注意在此没有创建设备节点
② file_operations fb_fops:
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
.ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fb_compat_ioctl,
#endif
.mmap = fb_mmap,
.open = fb_open,
.release = fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
.fsync = fb_deferred_io_fsync,
#endif
};
我们假设 app: open(“/dev/fb0”, …) 主设备号: 29, 次设备号: 0 //应用程序打开 /dev/fb0,主设备号29 次设备号0;那么就会调用内核中的 fb_open:
fb_open(struct inode *inode, struct file *file)
{
int fbidx = iminor(inode); // 得到次设备号 0
struct fb_info *info = registered_fb[fbidx(0)]; //fb_info 这个结构体等于registered_fb数组里面的次设备号检索出来。
}
我们假设 app: read() //应用程序read的时候;那么就会调用内核中的 fb_read:
fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
int fbidx = iminor(inode);//得到次设备号0
struct fb_info *info = registered_fb[fbidx];//在registered_fb数组里得到一个fb_info 结构体
}
由此可知open read都依赖fb_info结构体,从registered_fb数组中得到fb_info结构体。也就是说内核中主设备号为29的设备可能有很多,open的时候根据次设备号从registered_fb数组得到一个fb_info。
2、注册函数
register_framebuffer(struct fb_info*fb_info)
{
fb_info->dev = device_create(fb_class, fb_info->device,MKDEV(FB_MAJOR, i), "fb%d", i); //创建设备节点
registered_fb[i]= fb_info;
}
registered_fb数组在register_framebuffer被设置
现在应该已经可以很清晰看出LCD的框架。首先内核帮助我们实现了一个主设备号为29的设备,此时只创建了类,并没有在类下创建设备节点。 当我们的下层硬件驱动调用注册函数的时候,会初始化registered_fb结构体,并创建设备节点。此时应用程序可以来打开一个设备节点了,比如open(“/dev/fb0”, …),最终会调用到fbmem核心层提供的open函数,这个open函数中根据次设备号,registered_fb数组中取出硬件注册进来的结构体,调用里面的open函数,或者使用一些属性。这样内核可以方便管理类似的设备了。fbmem.c系统实现并抽象出来的,使用的时候依赖于底层框架实现,那么我们来写底层框架实现函数xxxfb.c上层fbmem.c内核已经写好,并完成上层驱动注册。我们要做的是写出硬件部分的函数,来初始化registered_fb:步骤
1.分配一个fb_info结构体: 怎么分配:framebuffer_alloc
2.设置fb_info里面的相关参数
3.注册:register_framebuffer
4.硬件相关的设置
3、底层框架函数将用到的结构体
fb_info 结构体:
struct fb_info {
int node;/* 序号索引值,/dev/fb0,/dev/fb1 其中0,1 就是从这里获得的*/
int flags;
struct fb_var_screeninfo var; /* Current var 可变参数,很重要 */
struct fb_fix_screeninfo fix; /* Current fix 固定参数,很重要 */
struct fb_monspecs monspecs; /* Current Monitor specs */
struct work_struct queue; /* Framebuffer event queue */
struct fb_pixmap pixmap; /* Image hardware mapper */
struct fb_pixmap sprite; /* Cursor hardware mapper */
struct fb_cmap cmap; /* Current cmap */
struct list_head modelist; /* mode list */
struct fb_videomode *mode; /* current mode */
#ifdef CONFIG_FB_BACKLIGHT
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */
struct backlight_device *bl_dev;
/* Backlight level curve */
struct mutex bl_curve_mutex;
u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
#ifdef CONFIG_FB_DEFERRED_IO
struct delayed_work deferred_work;
struct fb_deferred_io *fbdefio;
#endif
struct fb_ops *fbops;/* fb_ops,各种帧缓冲操作函数,很重要 */
struct device *device; /* This is the parent */
struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
char __iomem *screen_base; /* Virtual address "显存“的基地址 */
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 ”显存“的大小,重要 */
void *pseudo_palette; /* Fake palette of 16 colors */ /* 16位假的调色板,重要 */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32 state; /* Hardware state i.e suspend */
void *fbcon_par; /* fbcon use-only private area */
/* From here on everything is device dependent */
void *par; /* 这个用来存放私有数据 */
};
将用到下面6个结构体:
struct fb_var_screeninfo var; /*Current var 可变参数,很重要 * /
struct fb_fix_screeninfo fix; /* Current fix 固定参数,很重要 */
struct fb_ops fbops;/ fb_ops,各种帧缓冲操作函数,很重要 */
char __iomem screen_base; / Virtual address “显存“的基地址 */
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 ”显存“的大小,重要 */
void pseudo_palette; / Fake palette of 16 colors / / 16位假的调色板,重要 */
fb_var_screeninfo 结构体:
struct fb_var_screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what */
__u32 grayscale; /* != 0 Graylevels instead of colors */
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 reserved[5]; /* Reserved for future compatibility */
};
fb_fix_screeninfo fix结构体:
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */
};
fb_ops 结构体
struct fb_ops {
struct module *owner;
/* 打开/释放 */
int (*fb_open)(struct fb_info *info, int user);
int (*fb_release)(struct fb_info *info, int user);
/* 对于非线性布局的/常规内存映射无法工作的帧缓冲设备需要 */
ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos);
ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos);
/* 检测可变参数,并调整到支持的值*/
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
/* 根据 info->var 设置 video 模式 */
int (*fb_set_par)(struct fb_info *info);
/* 设置 color 寄存器 */
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info);
/* 批量设置 color 寄存器,设置颜色表 */
int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
/*显示空白 */
int (*fb_blank)(int blank, struct fb_info *info);
/* pan 显示 */
int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
/* 矩形填充 */
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
/* 数据复制 */
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
/* 图形填充 */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
/* 绘制光标 */
int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
/* 旋转显示 */
void (*fb_rotate)(struct fb_info *info, int angle);
/* 等待 blit 空闲 (可选) */
int (*fb_sync)(struct fb_info *info);
/* fb 特定的 ioctl (可选) */
int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
unsigned long arg);
/* 处理 32 位的 compat ioctl (可选) */
int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
unsigned long arg);
/* fb 特定的 mmap */
int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
/* 保存目前的硬件状态 */
void (*fb_save_state)(struct fb_info *info);
/* 恢复被保存的硬件状态 */
void (*fb_restore_state)(struct fb_info *info);
/* get capability given var */
void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
struct fb_var_screeninfo *var);
};
3、注册驱动时要做的事
先定义好各个结构体,framebufferUI使用platform总线注册,注册好device和driver,然后在probe函数中去填充好各个结构体,然后再分别去实现各个file_operations中的各个函数。最后注销
版权属于:孟超
本文链接:https://mengchao.xyz/index.php/archives/643/
转载时须注明出处及本声明
免费快递单号、淘宝快递单号、空包www.01kd.com