LCD设备驱动框架分析(数据结构)

来源:互联网 发布:什么样买卖数据 编辑:程序博客网 时间:2024/06/05 17:50

LCD设备驱动框架图

LCD设备驱动框架图

如上图所示

  • 核心层是通用的,不需要任何修改。驱动开发者只需要实现硬件设备驱动层
  • 帧缓冲设备可以看做是一个完整的子系统,主要由核心层的fbmem.c和硬件设备驱动层构成
  • 核心层代码fnmem.c向上提供了完整的字符设备操作接口,也就是实现注册字符设备,提供通用的open,read,write,ioctl,mmap等接口;向下给硬件设备驱动层提供标准的驱动编程接口;
  • linux系统中,一个硬件控制器(显卡)抽象为一个fb_info结构,要实现一个LCD驱动就是要实现这个结构,并且使用核心层提供的注册函数注册
  • fb_info中通过其中的fb_ops结构指针提供了实际硬件操作方法
  • fb_info中通过其中的fb_var_screeninfo结构和fb_fix_screeninfo结构提供了具体lcd屏基本信息
  • 注册:register_framebuffer
  • 注销:unregister_framebuffer

LCD驱动数据结构

LCD设备驱动核心结构体struct fb_info

地位等同于杂项设备的struct misc_dev结构
路径:fb.h linux-3.5\include\linux

struct fb_info {    atomic_t count;    int node;    int flags;    struct mutex lock;      /* Lock for open/release/ioctl funcs */    struct mutex mm_lock;       /* Lock for fb_mmap and smem_* fields */    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;    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 */ #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;    /* we need the PCI or similar aperture base/size not       smem_start/size as smem_start may just be an object       allocated inside the aperture so may not actually overlap */    struct apertures_struct {        unsigned int count;        struct aperture {            resource_size_t base;            resource_size_t size;        } ranges[0];    } *apertures;};

这个结构中成员很多大部分都是结构体,但写led驱动并不需要实现所有的成员,正如写字符设备驱动的file_operation那样,用到那个写哪个就可以。这里我们主要关注的是

    struct fb_var_screeninfo var;   /* LCD屏可变参数 */    struct fb_fix_screeninfo fix;   /* LCD屏固定参数 */    struct fb_ops *fbops;       /*真正操作硬件寄存器的方法集合*/    char __iomem *screen_base;  /* LCD虚拟显存地址 */    void *pseudo_palette;       /* 指向16种颜色的调试板,其实就是一块内存 */     void *par;                  /*私有数据,驱动开发者可以用来存放自己的数据的结构地址*/

var,fix,fbops,screen_base使用标准的LCD框架编写,这四个成员是一定要实现的。


struct fb_var_screeninfo

  • 路径:fb.h linux-3.5\include\linux
  • struct fb_var_screeninfo表示一个LCD控制器,记录了用户可以修改的的控制器参数,如屏幕的分辨率和bpp等,以及一些固定信息
struct fb_var_screeninfo {    __u32 xres;         /* 可见屏幕一行有多少像素点     */    __u32 yres;         /* 可见屏幕一屏有多少行  也就是列*/    __u32 xres_virtual;     /* 虚拟屏幕一行有多少像素点         */    __u32 yres_virtual;     /* 虚拟屏幕一屏有多少行           */    //显存大小并不一定等于实际屏幕显示对应的区域    __u32 xoffset;          /* 虚拟屏到实际屏的水平偏移量 */    __u32 yoffset;          /* 虚拟屏到实际屏的垂直偏移量 */    __u32 bits_per_pixel;       /*LCD屏工作时BPP            */    __u32 grayscale;        /* 0 = 彩色, 1 = 灰度屏, */    struct fb_bitfield red;     /* 红色的长度和偏移信息 */    struct fb_bitfield green;   /* 绿色的长度和偏移信息 */    struct fb_bitfield blue;    /* 蓝色的长度和偏移信息 */    struct fb_bitfield transp;  /* 透明色的长度和偏移信息*/        __u32 nonstd;           /* ==0,标准像素格式,一般情况基本都是标准像素!= 0 Non standard pixel format */   //定义修改参数生效时刻,一般马上生效,对应值是0,宏名是 FB_ACTIVATE_NOW    __u32 activate;         /* see FB_ACTIVATE_*        */    /*补充相关宏   #define FB_ACTIVATE_NOW      0   /*修改立即生效*/   #define FB_ACTIVATE_NXTOPEN  1   /* 下次打开时生效*/   #define FB_ACTIVATE_TEST 2   /* 不设置,忽略 */   */   //存放物理屏的物理尺寸,是外观尺寸,单位是mm,可选择填充的项  非重点    __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) */    /*下面是LCD屏的工作时序,对应前面移植LCD传递下来的 struct fb_videomode结构*/    __u32 pixclock;         /* pixel clock in ps (pico seconds) */    __u32 left_margin;      /* time from sync to picture    HBPD*/    __u32 right_margin;     /* time from picture to sync    HFPD*/    __u32 upper_margin;     /* time from sync to picture    VBPD*/    __u32 lower_margin;     /*                              VFPB*/    __u32 hsync_len;        /* length of horizontal sync    HSPW*/    __u32 vsync_len;        /* length of vertical sync      VSPW*/    __u32 sync;         /* see FB_SYNC_*        */    __u32 vmode;            /* see FB_VMODE_*       */    __u32 rotate;           /* angle we rotate counter clockwise */    __u32 colorspace;       /* colorspace for FOURCC-based modes */    __u32 reserved[4];      /* Reserved for future compatibility */};

补充struct fb_bitfield

struct fb_bitfield {    __u32 offset;           /* 颜色偏移量    */    __u32 length;           /* 颜色长度     */    __u32 msb_right;        /* != 0 :最高位在右边 */ };

struct fb_fix_screeninfo

  • 路径:fb.h linux-3.5\include\linux
struct fb_fix_screeninfo {    char id[16];            /* LCD标识名 填写一个16字符以内字符串即可 */    unsigned long smem_start;   /* 显存的物理起始地址,不是虚拟地址 */    __u32 smem_len;         /* 显存的内存长度 */    __u32 type;         /* see FB_TYPE_*  FB_TYPE_PACKED_PIXELS 表示像素类型,一般都是标准像素格式       */    __u32 type_aux;         /* Interleave for interleaved Planes */    __u32 visual;           /* see FB_VISUAL_*  表示颜色类型FB_VISUAL_TRUECOLOR 0表示真彩色        */     __u16 xpanstep;         /* zero if no hardware panning 硬件x轴平移 没有就为0  */    __u16 ypanstep;         /* zero if no hardware panning 硬件y轴平移 没有就为0*/    __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 capabilities;     /* see FB_CAP_*         */    __u16 reserved[2];      /* Reserved for future compatibility */};

重要成员:
id:lcd标识名,随便
smem_start:显存的物理起始地址,不是虚拟地址,驱动中定义的变量,普通动态分配内存的方法得到的都是虚拟地址。要得到物理地址必须使用专门的DMA内存分配函数

void *dma_alloc_writecombine(struct device *dev, size_t size,                       dma_addr_t *dma_handle, gfp_t flag)

函数功能:动态分配DMA内存,同时可以得到分配内存的虚拟地址和物理地址
参数:
dev:设备指针如果没有赋值NULL
size:内存大小
dma_handle:作为输出参数使用,存放分配到的内存对应的物理地址
flag:内存分配方式
返回值:分配到的内存的首地址

DMA缓冲区释放函数:

void dma_free_writecombine(struct device *dev, size_t size,                     void *cpu_addr, dma_addr_t dma_handle)

功能:释放由dma_alloc_writecombine分配的dma内存
参数:
dev:设备指针如果没有赋值NULL
size:内存大小
cpu_addr:dma_alloc_writecombine得到的虚拟地址首地址
dma_handle:作为输出参数使用,存放分配到的内存对应的物理地址
备注:因为lcd是利用DMA来搬运数据,而DMA模块只会使用物理地址,所以LCD驱动中需要记录物理地址

line_length:一行占用的内存字节数


LCD设备驱动硬件操作方法结构struct fb_ops

路径:fb.h linux-3.5\include\linux
这个结构是内核用来描述整整硬件的操作方法和数据结构。

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);    /* set color register */    int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,                unsigned blue, unsigned transp, struct fb_info *info);    /* 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 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);    /* wait for blit idle, optional */    int (*fb_sync)(struct fb_info *info);    /* perform fb specific ioctl (optional) */    int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,            unsigned long arg);    /* Handle 32bit compat ioctl (optional) */    int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,            unsigned long arg);    /* perform fb specific mmap */    int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);    /* get capability given var */    void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,                struct fb_var_screeninfo *var);    /* teardown any resources to do with this framebuffer */    void (*fb_destroy)(struct fb_info *info);    /* called at KDB enter and leave time to prepare the console */    int (*fb_debug_enter)(struct fb_info *info);    int (*fb_debug_leave)(struct fb_info *info);};

这个结构成员有很多,那么哪些是必须实现的呢?
常用的重要成员:
fb_open:当你的lcd不需要做什么特殊的初始化操作,这个方法可以不实现
fb_release:当你的应用程序不使用lcd设备的时候,需要做的事情在这里实现,一般不实现
fb_read:当你的lcd控制器使用的内存是独立显存的时候才需要使用,直接使用核心层read
fb_write:当你的lcd控制器使用的内存是独立显存的时候才需要使用,直接使用核心层write
fb_check_var:检测应用程序传递下来的可变参数是否合法。当你不提供给应用程序通过ioctl命令动态修改LCD可变参数时不需要实现。
fb_set_par:实现的功能是把可变参数设置到硬件寄存器中去
fb_blank:实现屏幕的黑屏白屏模式(开屏,关屏)
fb_fillrect:实现功能是填充矩形,如果是非独立显卡直接使用内核自带的函数cfb_fillrect
fb_copyarea:实现功能是区域复制,如果是非独立显卡直接使用内核自带的函数cfb_copyarea
fb_imageblit:实现功能是绘制位图,如果是非独立显卡直接使用内核自带的函数cfb_imageblit
fb_ioctl:实现功能是让用户通过ioctl接口调用这个函数对LCD进行特殊功能控制,如果控制器只实现了一般的标准功能,不需要实现,使用核心层默认的ioctl接口就可以了
fb_setcolreg:实现的功能是设置颜色寄存器
fb_mmap:实现的功能是把内核空间的分配的显存映射到用户空间中对应的mmap系统调用,当你的控制器是独显的时候才需要
必须实现的:fb_fillrectfb_copyareafb_imageblit一般情况下也会实现fb_check_varfb_set_par

原创粉丝点击