linux系統LCD驅動(一)

2021-10-05 18:22:49 字數 4554 閱讀 6634

出來工作兩年,隨著工作的深入,一直很少有時間寫部落格,並且隨著工作各種零碎的除錯,有時候很容易忘記自己所學的一些東西,近期就像用寫部落格來鞏固自己剛入門時的一些基礎知識以及往後學到的一些知識。

linux系統lcd驅動也稱framebuff驅動,驅動框架如下圖:

應用程式通過開啟裝置節點dev/graphics/fbx,然後通過字元裝置訪問的方式訪問lcd驅動。fbmem.c便是向系統註冊乙個字元裝置,並且提供的了字元裝置的操作介面,fb_read,fb_write,fb_ioctl等等。如下看**:

**路徑:

drivers/video/fbdev/core/fbmem.c

static

int __init

fbmem_init

(void

) fb_class =

class_create

(this_module,

"graphics");

if(is_err

(fb_class)

)return0;

err_class:

unregister_chrdev

(fb_major,

"fb");

err_chrdev:

remove_proc_entry

("fb"

,null);

return ret;

}#ifdef module

module_init

(fbmem_init)

;static

void __exit

fbmem_exit

(void

)module_exit

(fbmem_exit)

;

從上面看出fbmem_init,fbmem_exit等就是標準的核心初始化函式,其中fbmem_init中的register_chrdev是字元裝置裝置註冊的介面,說明我們的fbmem是標準的字元裝置驅動,並且裝置主裝置號是fb_major(該值巨集定義為29),既然是字元裝置驅動都會有檔案操作集合(這是我們第一次學習字元裝置便接觸的),這裡檔案操作集合便是fb_fops,**如下:

static

const

struct file_operations fb_fops =

;

當使用者空間訪問字元裝置驅動的時候,呼叫write的時候會有如下呼叫過程:

write()

-->

fb_write

()

那麼我們就從write介面的訪問角度來看整個系統的呼叫流程,如下是fb_write的實現:

static ssize_t

fb_write

(struct file *file,

const

char __user *buf, size_t count, loff_t *ppos)

if(count + p > total_size)

buffer =

kmalloc

((count > page_size)

? page_size : count,

gfp_kernel);if

(!buffer)

return

-enomem;

dst =

(u8 __iomem *

)(info->screen_base + p);if

(info->fbops->fb_sync)

info->fbops->

fb_sync

(info)

;while

(count)

fb_memcpy_tofb

(dst, src, c)

; dst +

= c;

src +

= c;

*ppos +

= c;

buf +

= c;

cnt +

= c;

count -

= c;

}kfree

(buffer)

;return

(cnt)

? cnt : err;

}

從上面的**看出fb_write主要是呼叫info->fbops->fb_write進行對底下底層硬體的操作,在該函式開頭info的定義

struct fb_info *info =

file_fb_info

(file)

;

static

struct fb_info *

file_fb_info

(struct file *file)

**不難看出,就是通過*file結合得到inode,然後通過inode獲取到次裝置號,這是因為我們的lcd可以有多個驅動載入,但主裝置號都是29,但是次裝置號可以有多個。然後根據次裝置號從registered_fb陣列中獲取到info。隨之而來的疑問,registered_fb在**初始化?

int

register_framebuffer

(struct fb_info *fb_info)

export_symbol

(register_framebuffer)

;static bool lockless_register_fb;

module_param_named_unsafe

(lockless_register_fb, lockless_register_fb, bool,

0400);

module_parm_desc

(lockless_register_fb,

"lockless framebuffer registration for debugging [default=off]");

static

intdo_register_framebuffer

(struct fb_info *fb_info)

else

fb_init_device

(fb_info);.

....

.fb_var_to_videomode

(&mode,

&fb_info->var)

;fb_add_videomode

(&mode,

&fb_info->modelist)

;//賦值registered_fb

registered_fb[i]

= fb_info;..

....

return0;

}

從上面看出registered_fb是個fb_info型別的全域性變數陣列,然後對外提供register_framebuffer–>do_register_framebuffer介面將已經初始化好的fb_info物件註冊到registered_fb中,registered_fb就是儲存了多個已經註冊好的fb_info物件。fb_info物件的的宣告:

struct fb_info 

;unsigned

long screen_size;

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 ranges[0]

;}*apertures;

bool skip_vt_switch;

/* no vt switch on suspend/resume required */

};

fb_info是底層lcd硬體與核心framebuffer字元裝置的橋梁,這是核心裝置的一種解耦方法吧,這樣子驅動工程師在移植或者除錯的時候只需要定義乙個fb_info物件並初始化fb_info的資訊,然後再通過register_framebuffer將fb_info註冊系統便可。

Linux的LCD驅動分析

linux的graphics子系統介紹 一 lcd介紹 liquid crystal display液晶顯示器,lcd按材料分有 stn 超扭曲陣列 tft 薄膜電晶體 ltps 低溫晶體多晶矽 oled 有機發光二極體 等。lcd的介面種類有 ttlrgb 數字rgb顏色介面 i80 又稱mcu介...

Linux高階驅動 LCD驅動框架分析

功能 給使用者提供介面 fbmem init 入口函式 1.申請主裝置號,註冊字元裝置 register chrdev fb major 29 fb fb fops 2.建立乙個裝置類 fb class class create this module,graphics static const s...

Linux 2 6 38的LCD驅動分析(一)

一 讓lcd顯示可愛的小企鵝 還是先說說環境吧,處理器為s3c6410,linux的版本是2.6.38 友善之臂提供的 下面先說說怎樣讓lcd上顯示出可愛的小企鵝。最直接的步驟如下 記住不要問為什麼哈 一步一步跟著走就行了 1.新增s3c6410處理器的lcd控制暫存器的初始值,具體做法為在檔案ar...