您的位置:首页 > 运维架构 > Linux

Linux下LCD驱动详细分析(一)

2013-08-16 22:54 399 查看
貌似好久好久没写驱动类的博客,距上一次写驱动的博客还得回到半年前,那时天气还很冷,如今已经热的要命,但我还是想把自己学习到的知识跟大家分享。没写驱动类的博客是觉得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,这个文件实现了帧缓冲设备驱动的文件操作接口函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: