1. 程式人生 > >linux--framebuffer驅動框架

linux--framebuffer驅動框架

一:framebuffer?

幀緩衝(一螢幕資料)(簡稱fb),核心中虛擬出的裝置,嚮應用層提供一個統一標準的顯示介面(frambuffer)。

容許應用層在圖形模式下直接對顯示緩衝區進行讀寫操作。

framebuffer用來操作物理視訊記憶體的位置,換頁機制等操作。

使用framebuffer時,linux將顯示卡置於圖形模式下。

framebuffer的裝置檔案: /dev/fb0。

1:對應的原始檔:linux/driver/video/總抽象裝置:fbcon.c(還有與各種顯示卡驅動相關的原始檔)

裝置驅動的原始檔:linux/driver/video/fbmem.c           linux/include/linux/fb.h(framebuffer的裝置資訊的標頭檔案)(主要用來分析這兩個檔案)

linux/drivers/video/fbgen.c或者linux/drivers/video目錄下的其它裝置驅動是比較好的參考資料。

分析結構體:

1:fb_info:

struct fb_info {   //用來描述一個fb裝置的結構體
    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 */ //fb的可變引數跟螢幕輸出有關係
    struct fb_fix_screeninfo fix;    /* Current fix */  //fb的固定引數
    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;     //對應的fb的操作函式
    struct device *device;        /* This is the parent */ //fb的父裝置
    struct device *dev;        /* This is this fb device */  //fb的當前裝置
    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 */ //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;
    /* 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;

    bool skip_vt_switch; /* no VT switch on suspend/resume required */
};

2;fb_var_screeninfo (fb的可變引數)

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 = color, 1 = grayscale,    */
                    /* >1 = FOURCC            */
    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    */ //物理高度mm
    __u32 width;            /* width of picture in mm     */ //物理寬度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) */ //畫素時鐘
    //lcd時序引數
    __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 colorspace;        /* colorspace for FOURCC-based modes */
    __u32 reserved[4];        /* Reserved for future compatibility */
};

3:fb_fix_screeninfo //fb的固定引數:顯示卡屬性,執行時不能被修改

  struct fb_fix_screeninfo {

  char id[16]; /* identification string eg "TT Builtin" */ID

  unsigned long smem_start; /* Start of frame buffer mem */ 記憶體起始

  /* (physical address) */ 實體地址

  __u32 smem_len; /* Length of frame buffer mem */ 記憶體大小

  __u32 type; /* see FB_TYPE_* */

  __u32 type_aux; /* Interleave for interleaved Planes */插入區域?

  __u32 visual; /* see FB_VISUAL_* */

  __u16 xpanstep; /* zero if no hardware panning */沒有硬體裝置就為零

  __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; /* Type of acceleration available */ 可用的加速型別

  __u16 reserved[3]; /* Reserved for future compatibility */

  };

4: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 */ 透明,可以為零

  };

5:struct fb_ops

  使用者應用可以使用ioctl()系統呼叫來操作裝置,這個結構就是用一支援ioctl()的這些操作的。

  struct fb_ops {

  /*開啟釋放有用的標誌 */

  struct module *owner;

  int (*fb_open)(struct fb_info *info, int user);

  int (*fb_release)(struct fb_info *info, int user);

  /* 得到固定引數*/

  int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con,struct fb_info *info);

    /* 設定顏色暫存器 */
    int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,unsigned blue, unsigned transp, struct fb_info *info);

  /* 得到改變引數 */

  int (*fb_get_var)(struct fb_var_screeninfo *var, int con,struct fb_info *info);

  /* 設定改變引數 */

  int (*fb_set_var)(struct fb_var_screeninfo *var, int con,struct fb_info *info);

    /* 批量設定顏色暫存器*/
    int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);

  /*得到色彩表 */

  int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con,struct fb_info *info);

    /*繪製一個矩形 */ //cfbfillrect.c
    void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
    /* 拷貝資料從一個區域到另一個區域 */ //cfbcopyarea.c檔案中(可編譯成.ko檔案)
    void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
    /*將影象繪製到顯示器 */ //cfbimgblt.c
    void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);

  /* 設定*/

  int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con,struct fb_info *info);

  /* 平移顯示 */

  int (*fb_pan_display)(struct fb_var_screeninfo *var, int con,struct fb_info *info);

  /*執行特定的ioctl*/

  int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg, int con, struct fb_info *info);

  /* 執行fb特定的mmap */

  int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);

  /*  切換到光柵影象模式*/

  int (*fb_rasterimg)(struct fb_info *info, int start); };

二:fbmem.c

處於裝置驅動的中心位置,它為上層的應用提供呼叫,也為下層的驅動提供介面,哪些硬體的驅動需要到這的介面來想體統註冊,fbmem.c為所有的framebuffer提供了通用的介面

1:檔案的全域性變數

struct fb_info *registered_fb[FB_MAX] __read_mostly; //所註冊的所有fb_info都儲存在該陣列中
int num_registered_fb __read_mostly;    //新增一個結構體,該引數自動+1;

  static struct {

  const char *name;

  int (*init)(void);

  int (*setup)(void);

  } fb_drivers[] __initdata= { ....}; //如果靜態連線到核心,對應新增到該表中,動態insmod。則不需要關心。

         framebuffer_alloc用來分配一個fb_info 結構體。

  register_framebuffer(struct fb_info *fb_info);         unregister_framebuffer(struct fb_info *fb_info);

是提供裝置驅動的介面,幾乎所有的底層裝置驅動所要做的事就是填充fb_info,用來註冊/登出自己,

注意分層的概念:裝置驅動向使用者程式提供呼叫介面,我們實現底層硬體操作定義file_operations結構體想系統提供呼叫介面。

static struct fb_info *file_fb_info(struct file *file):我們採用該函式來找到對應的註冊的fb_info結構體

其中fb_info中的struct fb_ops *fbops;是底層操作函式:file_operations:是上層系統呼叫介面,可直接呼叫,

當ioctl系統呼叫時,最終呼叫到介面到的fb_ops中的函式中,去支援這些操作。

  ioctl()系統呼叫在檔案fbmem.c中實現,通過觀察可以發現ioctl()命令與fb_ops’s 中函式的關係:

  FBIOGET_VSCREENINFO fb_get_var

  FBIOPUT_VSCREENINFO fb_set_var

  FBIOGET_FSCREENINFO fb_get_fix

  FBIOPUTCMAP fb_set_cmap

  FBIOGETCMAP fb_get_cmap

  FBIOPAN_DISPLAY fb_pan_display

 如果我們定義了fb_XXX_XXX 方法,使用者程式就可以使用FBIOXXXX巨集的ioctl()操作來操作硬體。

fb_set_var()是最重要的,它用於設定顯示卡的模式和其它屬性,下面是函式fb_set_var()的執行步驟:

  1)檢測是否必須設定模式

  2)設定模式

  3)設定顏色對映

  4) 根據以前的設定重新設定LCD控制器的各暫存器。

其中比較重要的步奏是設定底層的fb_ops操作函式。