linux驅動之framebuffer
第一部分 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
(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 去除)