LCD Driver 筆記 - Frame Buffer


LCD Driver 筆記 - Frame Buffer

什麼是framebuffer 設備:
framebuffer 是一種能夠提取圖形的硬件設備,是用戶進入圖形界面很好的接口。
有了framebuffer,用戶的應用程序不需要對底層的驅動的深入瞭解就能夠做出很好的圖形。
對於用戶而言,它和 /dev 下面的其他設備沒有什麼區別,用戶可以把 framebuffer 看成一塊內存,既可以向這塊內存中寫入數據,也可以從這塊內存中讀取數據。
第一個被註冊的 framebuffer 的 minor 等於0,第二個被註冊的 framebuffer的minor 等於 1,以此類推。其 major 都為 29。


framebuffer 內部結構說明:
相關檔案:
linux/include/linux/fb.h
linux/drivers/video/fbmem.c 

fb_var_screeninfo 是用來描述圖形卡的特性的。通常是被用戶設置的。 
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 resolution 可視區域的偏移 */  
     __u32 yoffset;


     __u32 bits_per_pixel;     /* 每一像素的bit數 */ 
     __u32 grayscale;          /* != 0 Gray levels 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; /* acceleration flags (hints) 加速標誌 */
     /* 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 reserved[6];    /* Reserved for future compatibility 備用-以後開發 
*/
};

fb_fix_screeninfo 定義了圖形卡的硬件特性,是不能改變的,用戶選定了哪一個圖形卡,那麼它的硬件特性也就定下來了。
struct fb_fix_screeninfo
{
     char id[16];                     /* identification string eg "TT Builtin" */      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 */
};

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 定義了當前圖形卡 framebuffer 設備的獨立狀態,一個圖形卡可能有兩個 framebuffer, 在這種情況下,就需要兩個 fb_info 結構。這個結構是唯一在內核空間可見的。
struct fb_info {
     char modename[40];            /* default video mode 默認的視頻卡類型 */
     kdev_t node;
     int flags;
     int open;                           /* Has this been open already? */
    
     #define FBINFO_FLAG_MODULE 1      /* Low-level driver is a module */
     struct fb_var_screeninfo var;           /* Current var 現在的視頻信息 */
     struct fb_fix_screeninfo fix;             /* Current fix 修正的信息 */
     struct fb_monspecs monspecs;        /* Current Monitor specs 現在的顯示器模式 */
     struct fb_cmap cmap;                    /* Current cmap 當前優先級 */
     struct fb_ops *fbops;
     char *screen_base;                       /* Virtual address 物理基址 */      struct display *disp;                      /* initial display variable 初始化 */
     struct vc_data *display_fg;            /* Console visible on this display */

     char fontname[40];                       /* default font name 默認的字體 */
     devfs_handle_t devfs_handle;         /* Devfs handle for new name */
     devfs_handle_t devfs_lhandle;        /* Devfs handle for compat. symlink 兼容 */
     int (*changevar)(int);                   /* tell console var has changed 告訴
                                                         console 變量修改了 */

     int (*switch_con)(int, struct fb_info*);
                                                     /* tell fb to switch consoles 告訴 fb 
                                                         選擇consoles */

     int (*updatevar)(int, struct fb_info*);
                                                  /* tell fb to update the vars 告訴 fb 更新變量 */
     void (*blank)(int, struct fb_info*); 
                                                     /* tell fb to (un)blank the screen 告訴 fb
                                                         使用黑白模式(或者不黑)
                                                         arg = 0: unblank 黑白模式
                                                         arg > 0: VESA level (arg-1)  
                                                                     選擇VESA模式 */ 
     
     void *pseudo_palette;                 /* Fake palette of 16 colors and the cursor's
                                                        color for nonpalette mode 修正調色板 */

    
     /* From here on everything is device dependent */
     void *par;
};
#include
#include
#include
#include
#include
#include
#include
#include
#include "bitmap.h"
int main()
{
        int fb;
        unsigned char* fb_mem; 
        
        // open frame buffer device
        fb= open("/dev/fb0", O_RDWR);

        // get frame buffer memory mapping address
        fb_mem = mmap (NULL, 320*240*2,
                                PROT_READ|PROT_WRITE, MAP_SHARED, fb, 0);
        
        // clear frame buffer
        memset(fb_mem, 0, 320*240*2);

        // cpoy image to framebuffer         memcpy(fb_mem, (unsigned char *)ScreenBitmap, 320*240*2); 

        // close framebuffer device
        close(fb); 

        return 0;
}
fb_ops 用戶應用可以使用 ioctl() 系統調用來操作設備,這個結構就是用一支持 ioctl() 的這些操作的。  (跟我在程式碼裡面看到的不太一樣??)
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);
     /* get non settable parameters */
     int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con, struct fb_info *info);
     /* get settable parameters */
     int (*fb_get_var)(struct fb_var_screeninfo *var, int con, struct fb_info *info);
     /* set settable parameters */      int (*fb_set_var)(struct fb_var_screeninfo *var, int con, struct fb_info *info);
     /* get colormap */
     int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con,
                                struct fb_info *info);
     /* set colormap */      int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con,
                                struct fb_info *info);
     /* pan display (optional) */
     int (*fb_pan_display)(struct fb_var_screeninfo *var, int con, 
                                  struct fb_info *info);
     /* perform fb specific ioctl (optional) */
     int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
                         unsigned long arg, int con, struct fb_info *info);
     /* perform fb specific mmap */
     int (*fb_mmap)(struct fb_info *info, struct file *file, 
                           struct vm_area_struct *vma);
     /* switch to/from raster image mode */
     int (*fb_rasterimg)(struct fb_info *info, int start);
};

LCD Frame buffer 函式呼叫順序:

s3c2410fb_probe():
- s3c2410fb_map_video_memory()
- s3c2410fb_init_registers()
- s3c2410fb_check_var()

s3c2410fb_set_par() -> s3c2410fb_activate_var():
- s3c2410fb_calculate_tft_lcd_regs()
- s3c2410fb_set_lcdaddr()

對 framebuffer 操作:

dd if=/dev/fb0 of=fbfile
可以將 fb0 中的內容保存下來存到 fbfile 裡 

如果顯示模式是 1024*768 的 8 位色
dd if=/dev/zero of=/dev/fb0 bs=1024 count=768
可以清空 framebuffer (螢幕全黑)
dd if=fbfile of=/dev/fb0
將 fbfile 內的資料寫回 framebuffer 

程式內對 framebuffer 操作: 
較新的 較舊