1. 程式人生 > >linux驅動之framebuffer

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 

   

一個幀緩衝區對應一個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 去除)