概述
貌似好久好久没写驱动类的博客,距上一次写驱动的博客还得回到半年前,那时天气还很冷,如今已经热的要命,但我还是想把自己学习到的知识跟大家分享。没写驱动类的博客是觉得Linux下的驱动源码真是太多太多了,半年前我也比较害怕Linux源代码,随时时间的推移,自己琢磨了不短时间了,觉得大概能读懂Linux源代码了,也就没那么害怕它了。
原归正传,预定以后的驱动博客我想用尽量短篇幅来记录,但是会以尽量详细的角度去分析驱动。学习驱动心得,驱动呢主要还是要抓住主干的架构,太细节的东西不必太刻意去研究,因为很多太底层的函数人家已经帮你实现了,你不必去怀疑它正确与否。
LCD驱动里有个很重要的概念叫帧缓冲(framebuffer),它是Linux系统为显示设备提供的一个接口,应用程序在图形模式允许对显示缓冲区进行读写操作。用户根本不用关心物理显示缓冲区的具体位置及存放方式,因为这些都由缓冲区设备驱动完成了。
启动开发板后执行ls /dev/fb* 命令可以看到,帧缓冲设备的主设备号为29,对应/dev/fbn设备文件,一般为/dev/fb0
在弄清楚LCD驱动架构之前,我们先弄清楚几个重要的结构体,为了减短篇幅,有一些不是很重要的成员会用省略,具体的源代码请大家参考Linux源代码,这里我使用的源代码是天嵌公司提供的移植好的Linux-2.6.30.4。
1.fb_info结构体(在include/linux/fb.h文件里定义)
struct fb_info {
int node; /* 序号索引值,/dev/fb0,/dev/fb1 其中0,1 就是从这里获得的*/
int flags;
struct mutex lock;/* 一般在 open/release/ioctl 函数里会用到的锁 */
struct fb_var_screeninfo var;/* 可变参数,很重要 */
struct fb_fix_screeninfo 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 */
。。。。。。
struct fb_ops *fbops;
struct device *device;/* This is the parent */
struct device *dev;/* This is this fb device */
。。。。。。
char __iomem *screen_base;/* "显存“的基地址 */
unsigned long screen_size; /* ”显存“的大小 */
void *pseudo_palette; /* 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; /* 这个用来存放私有数据 */
};
2.fb_ops结构体(在include/linux/fb.h文件里定义)
考虑到fb_ops结构体里面的函数指针成员太多,这里仅简单列举几个比较常见的,具体的请参考源代码。
struct fb_ops{
struct module *owner; /* 模块计数 */
int (*fb_open)(struct fb_info *info, int user); /* 打开函数,第一个参数为fb_info */
int (*fb_release)(struct fb_info *info, int user);
。。。。。。
/* fb_check_var函数用来检查可变参数,并调整修改可变参数 */
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
。。。。。。
/*fb_setcolreg函数就是用来设置fb_info里面的pseudo_palette调色板成员 */
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info);
。。。。。。
/* 下面三个是通用的函数 */
/* Draws a rectangle */
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
/* Copy data from area to another */
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
/* Draws a image to the display */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
。。。。。。
/* 有了fb_ioctl应用层可以通过ioctl系统调用来设置屏幕参数等 */
int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
unsigned long arg);
。。。。。。
/* 有了fb_mmap应用层可以通过mmap系统调用来读写帧缓冲区内存 */
int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
。。。
};
3.fb_var_screeninfo 结构体(在include/linux/fb.h文件里定义)
fb_var_screeninfo 被fb_info结构体所包含,这个结构体主要用来设置LCD屏幕的参数,如分辨率、像素比特数等,LCD驱动程序里面硬件相关的设置很多都涉及这个结构体。
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 */
};
4.fb_fix_screeninfo 结构体(在include/linux/fb.h文件里定义)
struct fb_fix_screeninfo {
char id[16];/* 驱动名字就保存在这里*/
unsigned long smem_start; /* fb缓冲区的基地址,这是一个物理地址 */
__u32 smem_len; /* fb缓冲区的长度 */
__u32 type; /* FB_TYPE_类型*/
__u32 type_aux;/* Interleave for interleaved Planes */
__u32 visual;/* FB_VISUAL_类型*/
__u16 xpanstep;/* 一般设置为0 */
__u16 ypanstep;/* 一般设置为0 */
__u16 ywrapstep;/* 一般设置为0 */
__u32 line_length;/* 屏幕一行有多个字节 */
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 */
};
以上笼统的介绍了几个重要的结构体,大家如果没有阅读过源码的可能对这些结构体比较陌生,但是没关系,比较常用的我都用显眼的颜色标记了,大家结合以后的博客日志就会懂这些结构有什么作用了。
对于这些参数会在哪里设置?通过什么样的形式来设置?
答:通过平台设备的方式来设置,这就是鼎鼎有名的platform_device结构体了,这个知识留到后面的LCD驱动篇来讲解。
这篇博客先分析到这里,下一篇准备讲内核源代码fbmem.c,这个文件实现了帧缓冲设备驱动的文件操作接口函数。
最后
以上就是动听溪流为你收集整理的Linux下LCD驱动详细分析(一)的全部内容,希望文章能够帮你解决Linux下LCD驱动详细分析(一)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复