什么是framebuffer
framebuffer從字面上理解是“幀緩沖”,一般有如下理解:
- 單純的把framebuffer看作一塊內存,這部分內存包含了將要scan out顯示的數據。
- 等價於framebuffer driver。通常作為LCD控制器或者其他顯示設備的驅動,FrameBuffer驅動是一個字符設備,設備節點是/dev/fbX,主設備號為29,次設備號遞增,用戶可以將Framebuffer看成是顯示內存的一個映像,將其映射到進程地址空間之后,就可以直接進行讀寫操作,而寫操作可以立即反應在屏幕上。這種操作是抽象的,統一的。用戶不必關心物理顯存的位置、換頁機制等等具體細節。這些都是由Framebuffer設備驅動來完成的。Framebuffer設備為上層應用程序提供系統調用,也為下一層的特定硬件驅動提供接口;那些底層硬件驅動需要用到這兒的接口來向系統內核注冊它們自己。所以可以看成是一個graphic hardware-independent抽象層,上面對接應用層,下面對接LCD等硬件的驅動。
- 有一種說法是操縱lcd顯示就是操縱framebuffer,表面上來看是這樣的。實際上是frambuffer就是linux內核驅動申請的一片內存空間,然后lcd內有一片sram,cpu內部有個lcd控制器,它有個單獨的dma用來將frambuffer中的數據拷貝到lcd的sram中去 拷貝到lcd的sram中的數據就會顯示在lcd上,LCD驅動和framebuffer驅動沒有必然的聯系,它只是驅動LCD正常工作的,比如有信號傳過來,那么LCD驅動負責把信號轉成顯示屏上的內容,至於什么內容這就是應用層要處理的。
- framebuffer幀緩沖(簡稱fb)是linux內核中虛擬出的一個設備
- framebuffer向應用層提供一個統一標准接口的顯示設備
- 從驅動來看,fb是一個典型的字符設備,而且創建了一個類/sys/class/graphics
幀緩沖設備驅動的結構
我們知道在Linux中,萬物都是文件。那么framebuffer也是一個文件,比如/dev/fb0。我們只需要操作/dev/fb0就可以把圖像顯示在顯示器上了,那么這是怎么實現的呢?
先談談如何把文件操作和設備操作關聯起來。
物理層面:
Linux中的PCI設備可以將其控制寄存器映射到物理內存空間,而后,對這些控制寄存器的訪問變成了對理內存的訪問,因此,這些寄存器又被稱為"memio"。一旦被映射到物理內存,Linux的普通進程就可以通過mmap將這些內存I/O映射到進程地址空間,這樣就可以直接訪問這些寄存器了。
邏輯層面:
FrameBuffer設備屬於字符設備,采用了文件層—驅動層的接口方式,Linux為幀緩沖設備定義了驅動層的接口fb_info結構,在文件層上,用戶調用file_operations的函數操作,間接調用fb_info中的fb_ops函數集來操作硬件。
這里的意思是說,對於Linux系統,其事先規定了對於文件的操作,也就是上面說的file_operations函數。我們只需要讓file_operations函數和fb_ops函數對應起來,就實現了文件 --> framebuffer driver的操作。這里的framebuffer dev實際上就是前文講的是一個抽象(或者說是虛擬)的設備。接下來就需要打通從framebuffer dev到具體設備的通路,也就是framebuffer driver --> LCD driver,實際上就是把framebuffer driver的fb_ops對應到lcd_ops。至於lcd_ops到硬件,什么樣的二進制代碼傳過去顯示怎樣的輸出,就是具體硬件廠商的人員所需要去實現的driver。
Framebuffer的使用步驟
- 打開設備文件 /dev/fb0
- 獲取當前設備信息 #include <linux/fb.h>
- mmap做映射
- 填充framebuffer
Framebuffer數據結構
kernel\include\linux\fb.h
fb_info是Linux為幀緩沖設備定義的驅動層接口。它不僅包含了底層函數,而且還有記錄設備狀態的數據。每個幀緩沖設備都與一個fb_info結構相對應。
struct fb_info { atomic_t count; int node; /*一個FrameBuffer設備的次設備號*/ 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 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 */ void *par; struct apertures_struct { unsigned int count; struct aperture { resource_size_t base; resource_size_t size; } ranges[0]; } *apertures; };
framebuffer驅動源碼分析
1. 驅動框架部分,即framebuffer driver相關
- drivers/video/fbmem.c主要任務:fbmen_init()函數負責創建graphics類、注冊FB的字符設備驅動、register_framebuffer()函數提供接口給具體framebuffer驅動編寫着來注冊fb設備。本文件相對於fb來說,地位和作用和misc.c文件相對於雜散類設備來說一樣的,結構和分析方法也是類似的。
- drivers/video/fbsys.c這個文件是處理fb在/sys目錄下的一些屬性文件的。
- drivers/video/modedb.c這個文件是管理顯示模式(譬如VGA、720P等就是顯示模式)的。
- drivers/video/fb_notify.c這個文件是frame buff用來管理相關通知的。
2. 驅動部分, 即lcd driver相關,以三星s3fdb為例,讀者沒有此driver可以分析amdgpu driver
- drivers/video/samsung/s3cfb.c驅動主體
- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c : 驅動主體
framebuffer驅動框架分析
Linux內核已經給我們封裝了LCD驅動的抽象層,我們只需要調用內核封裝的注冊接口去實現我們的平台驅動即可。
- 內核已經給我們封裝了LCD驅動的抽象層是在fbmem.c,先簡單分析一下它的框架。
- 總結
framebuffer驅動分析
1. s3cfb.c
2. s3c_device_fb
3. probe函數
- struct s3c_platform_fb :這個結構體是fb的platform_data結構體,這個結構體變量就是platform設備的私有數據,這個數據在platform_device.device.platform_data中存儲。在mach文件中去准備並填充這些數據,在probe函數中通過傳參的platform_device指針取出來。
- struct s3cfb_global: 這個結構體主要作用是在驅動部分的2個文件(s3cfb.c和s3cfb_fimd6x.c)的函數中做數據傳遞用的。
參考鏈接:
FrameBuffer驅動程序分析 https://blog.csdn.net/yangwen123/article/details/12096483
Linux驅動開發(9)------- framebuffer驅動詳解 https://blog.csdn.net/qq_45544223/article/details/106598190