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

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

猜你喜欢

转载自blog.csdn.net/z961968549/article/details/78821082