http://blog.chinaunix.net/u1/49924/showart_507500.html 四、s3c2410fb_ops變量詳解 在上面的文字中,較為詳細(xì)的解釋了platform device相關(guān)的代碼,通過上面的代碼的執(zhí)行,一個platform設(shè)備(framebuffer被當(dāng)作了platform設(shè)備)就加載到內(nèi)核中去了。就像一個PCI的網(wǎng)卡被加入到內(nèi)核一樣,不同的是PCI的網(wǎng)卡占用的是PCI總線,內(nèi)核會直接支持它。而對于platform設(shè)備需要用上面軟件的方法加載到內(nèi)核,同PCI網(wǎng)卡一樣,設(shè)備需要驅(qū)動程序,剛才只是將platform設(shè)備注冊到內(nèi)核中,現(xiàn)在它還需要驅(qū)動程序,本節(jié)中就來看看這些驅(qū)動。4.1 static struct fb_ops s3c2410fb_ops 對于s3c2410的framebuffer驅(qū)動支持的操作主要有s3c2410fb_ops變量中定義,該變量類型為struct fb_ops,該類型的定義在include/linux/fb.h文件中。它的相關(guān)解釋可以在http://www.91linux.com/html/article/kernel/20071204/8805.html頁面中找到,當(dāng)然在fb.h中也有很詳細(xì)的說明。下面看看對于s3c2410的驅(qū)動為該framebuffer提供了哪些操作。
static struct fb_ops s3c2410fb_ops = {
.owner = THIS_MODULE,
.fb_check_var = s3c2410fb_check_var, .fb_set_par = s3c2410fb_set_par, .fb_blank = s3c2410fb_blank,
.fb_setcolreg = s3c2410fb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit,}; 上面的代碼描述了支持的相關(guān)操作,下面主要會解釋s3c2410****的函數(shù),從.fb_fillrect開始的三個函數(shù)將不會被提及,當(dāng)然也可以去看看它們的行為是什么。這里還有一個問題要說明一下,就是s3c2410fb_ops是在什么時候被注冊的,這個問題的答案可以在s3c2410fb_probe函數(shù)中找到,請查看s3c2410fb_probe分析的那一小節(jié)。 4.2.1 s3c2410fb_check_var 在上面的小節(jié)中提到對于一個LCD屏來說內(nèi)核提供了兩組數(shù)據(jù)結(jié)構(gòu)來描述它,一組是可變屬性(fb_var_screeninfo描述),另一組是不變屬性(fb_fix_screeninfo描述)。對于可變屬性,應(yīng)該防止在操作的過程中出現(xiàn)超出法定范圍的情況,因此內(nèi)核應(yīng)該可以調(diào)用相關(guān)函數(shù)來檢測、并將這些屬性固定在法定的范圍內(nèi),完成這個操作的函數(shù)就是s3c2410_check_var。下面簡單說明一下該函數(shù)要做的事情,在這里最好看著fb_var_screeninfo和fb_info的定義。 static int s3c2410fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{ struct s3c2410fb_info *fbi = info->par; //得到驅(qū)動的私有數(shù)據(jù)信息,注意info-par的值……/* 下面檢查fb_var_screeninfo的xres和yres的值是否超出法定范圍,如果查出將其設(shè)定為正確的值。*/ if (var->yres > fbi->mach_info->yres.max)
var->yres = fbi->mach_info->yres.max;
else if (var->yres < fbi->mach_info->yres.min)
var->yres = fbi->mach_info->yres.min;
if (var->xres > fbi->mach_info->xres.max)
var->yres = fbi->mach_info->xres.max;
else if (var->xres < fbi->mach_info->xres.min)
var->xres = fbi->mach_info->xres.min;
…… /* 羨慕開始檢查bpp(表示用多少位表示一個像素),如果不合法,將其設(shè)置正確*/ if (var->bits_per_pixel > fbi->mach_info->bpp.max)
var->bits_per_pixel = fbi->mach_info->bpp.max;
else if (var->bits_per_pixel < fbi->mach_info->bpp.min)
var->bits_per_pixel = fbi->mach_info->bpp.min;
/* 下面的代碼根據(jù)bpp設(shè)置正確的顏色信息,代碼略 */
…… } return 0;} 4.2.2 s3c2410fb_set_par 該函數(shù)的主要工作是重新設(shè)置驅(qū)動的私有數(shù)據(jù)信息,主要改變的屬性有bpp和行的長度(以字節(jié)為單位)。這些屬性值其實是存放在fb_fix_screeninfo結(jié)構(gòu)中的,前面說過這些值在運行基本是不會改變的,這些不可改變的值又可分為絕對不能改變和允許改變的兩種類型,前一種的例子就是幀緩沖區(qū)的起始地址,后一種的例子就是在s3c2410fb_set_par函數(shù)中提到的屬性。假如應(yīng)用程序需要修改硬件的顯示狀態(tài)之類的操作,這個函數(shù)就顯得十分重要。 static int s3c2410fb_set_par(struct fb_info *info){ struct s3c2410fb_info *fbi = info->par; //得到私有數(shù)據(jù)信息 struct fb_var_screeninfo *var = &info->var; //可變的數(shù)據(jù)屬性
switch (var->bits_per_pixel) //根據(jù)bpp設(shè)置不變屬性信息的顏色模式 { case 16: fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR; //真彩色
break; case 1: fbi->fb->fix.visual = FB_VISUAL_MONO01; // 單色 break; default: fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; //偽彩色 break; } fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8; //修改行長度信息(以字節(jié)為單位),計算方法是一行中的(像素總數(shù) * 表達每個像素的位數(shù))/8。
…… s3c2410fb_activate_var(fbi, var); //該函數(shù)實際是設(shè)置硬件寄存器,解釋略。 return 0;}4.2.3 s3c2410fb_blank和s3c2410fb_setcolreg 對于s3c2410fb_blank函數(shù)實現(xiàn)的功能非常簡單,而且也有較詳細(xì)的說明,因此對它的說明就省略了。s3c2410fb_setcolreg函數(shù)的功能是設(shè)置顏色寄存器。它需要6個參數(shù),分別代表寄存器編號,紅色,綠色,藍(lán)色,透明和fb_info結(jié)構(gòu)。static int s3c2410fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
unsigned transp, struct fb_info *info){ struct s3c2410fb_info *fbi = info->par; //得到私有數(shù)據(jù)信息 unsigned int val;…… switch (fbi->fb->fix.visual) { case FB_VISUAL_TRUECOLOR: //真彩色,使用了調(diào)色板 /* true-colour, use pseuo-palette */
if (regno < 16) { u32 *pal = fbi->fb->pseudo_palette;
val = chan_to_field(red, &fbi->fb->var.red); //根據(jù)顏色值生成需要的數(shù)據(jù) val |= chan_to_field(green, &fbi->fb->var.green);
val |= chan_to_field(blue, &fbi->fb->var.blue);
pal[regno] = val; } break; case FB_VISUAL_PSEUDOCOLOR: //偽彩色 if (regno < 256) { /* 當(dāng)前假設(shè)為 RGB 5-6-5 模式 */
val = ((red >> 0) & 0xf800);
val |= ((green >> 5) & 0x07e0);
val |= ((blue >> 11) & 0x001f); writel(val, S3C2410_TFTPAL(regno)); //將此值直接寫入寄存器 schedule_palette_update(fbi, regno, val); //相關(guān)寄存器
} break; default: return 1; /* unknown type */ } return 0;} 到目前為止,整個驅(qū)動的主要部分已經(jīng)解釋完畢了。最后還是得提一下中斷處理函數(shù)s3c2410fb_irq,這個函數(shù)實現(xiàn)也比較短,它的主要調(diào)用了s3c2410fb_write_palette函數(shù)將它的功能是將調(diào)色板中的數(shù)據(jù)顯示到LCD上。兩個函數(shù)的實現(xiàn)也不難,這里就不再贅述。OK!good bye everyone!see you next time。
The End ------ anmnmnly ------ 2008.03.25