第一部分 framebuffer 概念介紹
1、framebuffer幀緩沖
幀緩沖(framebuffer)是Linux系統為顯示設備提供的一個接口,它將顯示緩沖區抽象,屏蔽圖像硬件的底層差異,允許上層應用程序在圖形模式下直接對顯示緩沖區進行讀寫操作。用戶不必關心物理顯示緩沖區的具體位置及存放方式,這些都是由幀緩沖設備驅動本身來完成。
framebuffer機制模仿顯卡的功能,將顯卡硬件結構抽象為一系列的數據結構,可以通過對framebuffer的讀寫直接對顯存進行操作。用戶可以將framebuffer看成是顯卡的一個映像,將其映射到進程空間后,就可以直接讀寫操作,寫操作會直接反映在屏幕上。
framebuffer是一個字符設備,主設備號是29,對應於/dev/fb%d設備文件。通常,使用如下方式(數字代表次設備號)
0 = /dev/fb0 第一個fb設備
1 = /dev/fb1 第二個fb設備
fb也是一種普通的內存設備,可以讀寫其內容。例如,屏幕抓屏:cp /dev/fb0 myfilefb 雖然可以向內存設備(/dev/mem)一樣,對其read、write、seek以及mmap。但區別在於fb使用的不是整個內存區。而是顯存部分。
2、fb與應用程序的互交
對於應用程序而言,它和其它的設備並沒有什么區別,用戶可以把fb看成是一塊內存,既可以向內存中寫數據,也可以讀數據。fb的顯示緩沖區位於內核空間。應用程序可以把此空間映射到自己的用戶空間,再進行操作。
在應用程序中,操作/dev/fbn的一般步驟如下:
(1)打開/dev/fbn設備文件。
(2)用ioctl()操作取得當前顯示屏幕的參數,如屏幕的分辨率、每個像素點的比特數。根據屏幕的參數可計算屏幕緩沖區的大小。
(3)用mmap()函數,將屏幕緩沖區映射到用戶空間。
(4)映射后就可以直接讀/寫屏幕緩沖區,進行繪圖和圖片顯示。
第二部分 framebuffer數據結構分析
framebuffer涉及的數據結構如下:
(1)struct fb_info
一個幀緩沖區對應一個struct fb_info結構,它包括了幀緩沖設備的屬性和操作的完整集合,每個幀設備都有一個fb_info結構體。
(2)struct fb_ops
結構體用來實現對幀緩沖設備的操作,這些函數需要驅動開發人員編寫,
(3)struct fb_fix_screeninfo
該結構體記錄了用戶不能修改的固定顯示控制器參數。這些固定的參數如緩沖區的物理地址、緩沖區的長度等等。
(4)struct fb_var_screeninfo
結構體中存儲了用戶可以修改的顯示器控制參數,例如屏幕分辨率、透明度等等。
(5)struct fb_cmap
結構體中記錄了顏色板信息,即調色板信息。,用戶空間可以通過ioctl()的FBIOGETCMAP和 FBIOPUTCMAP命令讀取或設定顏色表。
以上結構體的關系如下:
(6)struct fb_bitfield
結構體描述每一像素顯示緩沖區的組織方式,包含位域偏移、位域長度和MSB 指示。
第三部分 framebuffer核心層框架分析
framebuffer設備在Linux中是以平台設備形式存在的,fb設備驅動核心層為上層提供了系統調用,為底層驅動提供了接口,核心層的主文件及其功能如下。
(1)drivers/video/fbmem.c。主要任務:1、創建graphics類、注冊FB的字符設備驅動、提供register_framebuffer接口給具體framebuffer驅動編寫着來注冊fb設備的。本文件相對於fb來說,地位和作用和misc.c文件相對於雜散類設備來說一樣的,結構和分析方法也是類似的。
(2)drivers/video/fbsys.c。這個文件是處理fb在/sys目錄下的一些屬性文件的。
(3)drivers/video/modedb.c。這個文件是管理顯示模式(譬如VGA、720P等就是顯示模式)的
(4)drivers/video/fb_notify.c
fbmem_init函數
(1)#ifdef MODULE
(2)fb_proc_fops和fb在proc文件系統中的表現
(3)register_chrdev注冊fb設備
(4)class_create創建graphics類
(5)fbmem_exit的對應
fb_fops
(1)為應用層實現read/write/mmap/ioctl在驅動層的接口
(2)registered_fb和num_registered_fb
(3)struct fb_info register_framebuffer函數
(1)fb驅動框架開放給驅動編寫着的注冊接口
(2)fb_check_foreignness
(3)remove_conflicting_framebuffers
(4)device_create
(5)fb_init_device
fb在sysfs中的接口
(1)device_attrs
(2)dev_set_drvdata和dev_get_drvdata
注冊登記該fb設備
(1)registered_fb[i] = fb_info;
(2)結合fb_read等函數中對fb_info的使用
(3)關鍵點:數據如何封裝、數據由誰准備由誰消費、數據如何傳遞
第四部分 framebuffer驅動層分析
驅動層涉及源碼文件:
(1)drivers/video/samsung/s3cfb.c,驅動主體,主要是處理和數據結構有關的
(2)drivers/video/samsung/s3cfb_fimd6x.c,里面有很多LCD硬件操作的函數,主要是處理和硬件有關的
(2)arch/arm/mach-s5pv210/mach-x210.c,負責提供platform_device的
(3)arch/arm/plat-s5p/devs.c,為platform_device提供一些硬件描述信息
s3cfb.c文件probe函數分析
(1)struct s3c_platform_fb *pdata;
struct s3c_platform_fb 這個結構體是fb的platform_data結構體,這個結構體變量就是platform設備的私有數據,這個數據在platform_device.device.platform_data中存儲。在mach文件中去准備並填充這些數據,在probe函數中通過傳參的platform_device指針取出來。
(2)struct s3cfb_global 這個結構體主要作用是在驅動部分的2個文件(s3cfb.c和s3cfb_fimd6x.c)的函數中做數據傳遞用的。
(3)struct resource
(4)regulator
mach-x210.c文件分析
smdkc110_machine_init函數里面主要是做了一些該平台下數據的初始化,里面涉及fb的由兩個部分,如下:
(1)platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices)); //存放平台數據
smdkc110_devices
s3c_device_fb
(2)s3cfb_set_platdata(&ek070tn93_fb_data); //主要是用於提供設置GPIO的函數
第五部分 修改內核logo
1、找一個需要顯示的logo的png格式的圖片(圖片分辨率不得大於屏幕分辨率),並將其命令為logo.png
2、在終端下執行以下命令
pngtopnm logo.png | ppmquant -fs 224 | pnmtoplainpnm > logo_linux_clut224.ppm
3、將生成的ppm文件拷貝到替換掉/root/porting_x210/kernel/x210kernel/drivers/video/logo/目錄下
並將其改名為logo_x210_clut224.ppm
4、make
備注:
(1)修改fbmem.c的471行可以修改Logo顯示的位置,例如,顯示在屏幕中間:
image.dx = (info->var.xres - logo->width)/2;
image.dy = (info->var.yres - logo->height)/2;
(2)如果圖片顯示不出來可能有以下原因
a、內核里framebuffer的分辨率不對,可以在mach-x210.c的225行修改(1024 * 600);
b、只能在左上角顯示,CONFIG_FRAMEBUFFER_CONSOLE宏可能被選中(該宏不需要勾選,可以現在.config里面查看,確定后,make menuconfig 去除)