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[];
} *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[]; /* 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[]; /* 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[]; /* 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_fillrect
,
fb_copyarea
,
fb_imageblit
一般情況下也會實作
fb_check_var
,
fb_set_par