LCD设备驱动(二)

来源:互联网 发布:ubuntu磁盘空间查看 编辑:程序博客网 时间:2024/05/22 00:52
莫道不销魂 帘卷西风 人比黄花瘦 ——李清照

上篇我们粗略的学习了LCD一些硬件相关知识,本篇文章我们学习一下LCD最重要的设备:framebuffer(帧缓冲设备)

        framebuffer是Linux系统为显示设备提供的一个接口,它显示缓冲区抽象,屏蔽图像硬件的底层差异,即允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不用关系物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身完成,对于帧缓冲设备,只需要在显示缓冲区中与显示点对应的区域写入颜色值,对应的颜色就自动在屏幕上显示。可供用户态进程实现直接写屏,模仿显卡功能,将显卡硬件结构抽象掉,通过framebuffer这个设备直接对显存进行操作,将framebuffer看成显示内存的一个映像,将其映射到进程地址空间以后,进行直接读写操作,而且可以立即反应在屏幕上但Framebuffer本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池.CPU将运算后的结果放到这个水池,水池再将结果流到显示器. 中间不会对数据做处理. 应用程序也可以直接读写这个水池的内容.在这种机制下,尽管Framebuffer需要真正的显卡驱动的支持,但所有显示任务都由CPU完成

framebuffer是标准字符设备,主设备号29,对应/dev/fbxx设备文件

接下来我们来了解一下framebuffer相关的数据结构和函数:

1、fb_info结构体。
这是framebuffer最关键的一个数据结构体,其中包括了framebuffer设备属性和操作的完整描述:
struct fb_info {int node;    //一个特定的framebuffer,相当于一个次设备号int flags;struct mutex lock;/* Lock for open/release/ioctl funcs */互斥锁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 */图像硬件mapperstruct fb_pixmap sprite;/* Cursor hardware mapper */光标硬件mapperstruct fb_cmap cmap;/* Current cmap */当前的调色板struct list_head modelist;      /* mode list */struct fb_videomode *mode;/* current mode */当前的视频模式#ifdef CONFIG_FB_BACKLIGHT如果配置了LCD支持背光灯/* 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_IOstruct delayed_work deferred_work;struct fb_deferred_io *fbdefio;#endif
struct fb_ops *fbops;帧缓冲操作函数集struct device *device;/* This is the parent */父设备struct device *dev;/* This is this fb device */fb设备int class_flag;                    /* private sysfs flags */私有的sysfs标志#ifdef CONFIG_FB_TILEBLITTINGstruct fb_tile_ops *tileops;    /* Tile Blitting */图块blitting#endifchar __iomem *screen_base;/* Virtual address */虚拟基地址unsigned long screen_size;/* Amount of ioremapped VRAM or 0 */ ioremap的虚拟内存大小void *pseudo_palette;/* Fake palette of 16 colors */ 伪16位调色板#define FBINFO_STATE_RUNNING 0#define FBINFO_STATE_SUSPENDED 1u32 state; /* Hardware state i.e suspend */硬件的状态void *fbcon_par;                /* fbcon use-only private area *//* From here on everything is device dependent */void *par; };
fb_info结构体记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及操作函数指针,每一个帧缓冲设。备都对应一个fb_info。

2、fb_ops结构体
可以从上面得知fbops为fb_info的成员变量,它是指向底层操作的函数的指针,它是提供给底层设备驱动的一个接口。通常我们编写字符驱动的时候,要填写一个file_operations结构体,并使用register_chrdev()注册之,以告诉Linux如何操控驱动。当我们编写一个FrameBuffer的时候,就要依照Linux FrameBuffer编程的套路,填写fb_ops结构体。这个fb_ops也就相当于通常的file_operations结构体。
struct fb_ops {/* open/release and usage marking */struct module *owner;          打开和释放int (*fb_open)(struct fb_info *info, int user);int (*fb_release)(struct fb_info *info, int user);          这两个函数对于非线性布局的/常规内存映射无法工作的帧缓冲设备需要/* For framebuffers with strange non linear layouts or that do not* work with normal memory mapped access*/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);           检测可变参数,并调整到支持的值/* checks var and eventually tweaks it to something supported,* DO NOT MODIFY PAR */int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);            设置视频模式/* set the video mode according to info->var */int (*fb_set_par)(struct fb_info *info);           设置color寄存器的值/* set color register */int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,   unsigned blue, unsigned transp, struct fb_info *info);            批量设置color寄存器,设置颜色表/* set color registers in batch */int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);          显示空白/* blank display */int (*fb_blank)(int blank, struct fb_info *info);          pan显示/* pan display */int (*fb_pan_display)(struct fb_var_screeninfo *var, 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);           绘制光标/* Draws cursor */int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);            旋转显示/* Rotates the display */void (*fb_rotate)(struct fb_info *info, int angle);            等待blit空闲/* wait for blit idle, optional */int (*fb_sync)(struct fb_info *info);             fb特定的ioctl操作/* perform fb specific ioctl (optional) */int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,unsigned long arg);              处理32兼容的ioctl操作/* Handle 32bit compat ioctl (optional) */int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,unsigned long arg);             fb特定的mmap操作/* perform fb specific mmap */int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);           保存目前的硬件状态/* save current hardware state */void (*fb_save_state)(struct fb_info *info);            恢复被保存的硬件状态/* restore saved state */void (*fb_restore_state)(struct fb_info *info);           通过fb_info获得framebuffer的能力/* get capability given var */void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,   struct fb_var_screeninfo *var);};
其中的fb_check_var( )函数用来检查可以修改的屏幕参数并调整到合适的值,fb_set_par( )可以使得用户设置的屏幕参数在硬件上有效。

3、fb_var_screeninfo结构体(在fb.h头文件中)
描述显卡特性以及时序(显示器的显示方法),记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数。其中xres定义屏幕一行的点数,yres定义屏幕一列的点数,bits_per_pixel定义每个点用多少个字节表示:
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, fb缓存的R\G\B位域 */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) 除了pixclock本身,其他的都以像素时钟为单位*/__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结构体
显卡被设定模式后创建,描述显卡属性,不能被修改,因为模式被设定后,内存信息由显卡硬件给出,不能被改变记录用户不能修改的显示控制的参数,帧缓冲设备进行映射操作时,从这里取得缓冲区物理地址,这些都要在驱动程序中初始化和设置。
struct fb_fix_screeninfo {char id[16];/* identification string eg "TT Builtin"字符串形式标识符 */unsigned long smem_start;/* Start of frame buffer mem fb缓存开始位置*//* (physical address) */__u32 smem_len;/* Length of frame buffer mem fb缓存长度*/__u32 type;/* see FB_TYPE_**/__u32 type_aux;/* Interleave for interleaved Planes 分界*/__u32 visual;/* see FB_VISUAL_**/ __u16 xpanstep;/* zero if no hardware panning 没有硬件就给0 */__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  内存映射I/O起始位置 *//* (physical address) */__u32 mmio_len;/* Length of Memory Mapped I/O  内存映射I/O长度*/__u32 accel;/* Indicate to driver which*//*  specific chip/card we have*/__u16 reserved[3];/* Reserved for future compatibility */};

5、fb_cmap结构体
描述设备无关的颜色映射信息,通过FBIOGETCMAP 和 FBIOPUTCMAP 对应的ioctl操作设定获取颜色映射信息。
struct fb_cmap {__u32 start;/* First entry第一个元素入口*/__u32 len;/* Number of entries 元素个数*/__u16 *red;/* Red values颜色*/__u16 *green;__u16 *blue;__u16 *transp;/* transparency, can be NULL 透明度*/};

到这里我们可以发现上述几个重要的结构体均在fb_info结构体中。

6、s3c2410fb_display
这个结构体都是关于LCD的参数。
struct s3c2410fb_display {      /* LCD type */      unsigned type;        /* Screen size */      unsigned short width;      unsigned short height;        /* Screen info */      unsigned short xres;      unsigned short yres;      unsigned short bpp;        unsigned pixclock;           /* pixclock in picoseconds */      unsigned setclkval;          /* clkval */      unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */      unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */      unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */      unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */      unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */      unsigned short vsync_len;    /* value in lines (TFT) or 0 (STN) */        /* lcd configuration registers */      unsigned long   lcdcon5;  };  
上面很多参数在前面都解释过了。

7、smdk2440_lcd_cfg结构体
这个就是我们自己来配置LCD的参数的结构体了
static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {.lcdcon5= S3C2410_LCDCON5_FRM565 |  S3C2410_LCDCON5_INVVLINE |  S3C2410_LCDCON5_INVVFRAME |  S3C2410_LCDCON5_PWREN |  S3C2410_LCDCON5_HWSWP,.type= S3C2410_LCDCON1_TFT,.width= 480,   //屏幕宽度.height= 272,   //屏幕高度.pixclock= 40000, /* HCLK 100 MHz, divisor 1 */  //像素时钟.xres= 480,    //水平可见有效像素.yres= 272,    //垂直可见有效像素.bpp= 16,     //色位模式.left_margin= 19,  //行切换,从同步到绘图之间的延迟.right_margin= 10,  //行切换,从绘图到同步之间的延迟 .hsync_len= 30,    //水平同步的长度.upper_margin= 4,  //帧切换,从同步到绘图之间的延迟.lower_margin= 2,  //帧切换,从绘图到同步之间的延迟.vsync_len= 8,     //垂直同步的长度};
这里我的屏是4.3寸,分辨率480*272的。

8、
static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {.displays= &smdk2440_lcd_cfg,   //应用上面的信息.num_displays= 1,.default_display = 0,#if 0    /* currently setup by downloader */.gpccon= 0xaa940659,.gpccon_mask= 0xffffffff,.gpcup= 0x0000ffff,.gpcup_mask= 0xffffffff,.gpdcon= 0xaa84aaa0,.gpdcon_mask= 0xffffffff,.gpdup= 0x0000faff,.gpdup_mask= 0xffffffff,#endif.lpcsel=0, //((0xCE6) & ~7) | 1<<4,     三星的参数,我们不要或者设为0};
这个结构体就是用来实现上面LCD的配置的。至于上面的未使能的那段代码暂时还不理解。

9、还有一个结构体来定义上面那些量,这里包含了s3c2410fb_display结构体:
struct s3c2410fb_mach_info {      struct s3c2410fb_display *displays;     //s3c2410fb_display结构体      unsigned num_displays;                  //displays的个数      unsigned default_display;               //默认的default_display个数        /* GPIOs */      unsigned long   gpcup;                  //GPC      unsigned long   gpcup_mask;      unsigned long   gpccon;      unsigned long   gpccon_mask;      unsigned long   gpdup;                  //GPD      unsigned long   gpdup_mask;      unsigned long   gpdcon;      unsigned long   gpdcon_mask;        /* lpc3600 control register */      unsigned long   lpcsel;  };  


好了,写了这么多,休息一下,下一篇再继续吧。


2 0
原创粉丝点击