爲EVB添加 Frame Buffer驅動(一):基本套路

 一個嵌入式系統如果有了LCD顯示,那肯定會添彩不少,正好俺們的EVB上是標配LCD的,所以可以給它添個Frame Buffer驅動。以前改過S3C2410的Frame Buffer驅動,代碼過於冗長,而且S3C2410是是大戶人家的東東,自己帶LCD控制器,可以直接支持“玻璃“也可以支持模組(通過總線)的,關於玻璃和模組請看文章後面的備註。俺們設計芯片的原則不是Low Cost, 而是Ultra Low Cost,還美名其曰ULC。不過好歹也是個外企,雖然在51Job上叫外企(其它),我們還是有一個專門的硬件模塊LCD Bridge來接LCD模組的,包括了經典51單片機書上講的通過74xx芯片生成RS, WR,RD,CS信號的電路,主要在於沒有哪個做手機的用戶會在一堆BGA中間加兩個突兀的SOC封裝74xx,明顯不專業嘛,所以我們只能依了客戶。此外這個LCD Bridge裏面還有一點FIFO和顏色轉換的東東。FIFO還有點用,那個顏色轉換到目前爲止還沒用過。

      寫Linux程序如果說還要Start From Scratch,明顯Out了,沒看大家張嘴閉嘴都是”移植......移植“還是”移植“嗎?最經典的模板當然非skeletonfb.c莫數了,不過這個文件註釋居多,有效內容太少。我還是選一個實際一點的,對driver/video按照大小排序,最後在矮子裏面找高個,發現q40fb.c資質不錯,就是它了。

     第一步當然是要把q40fb.c該個名字cbp-fb.c,放到driver/video下面,然後添加Kconfig和Makefile選項使它能被編譯了,照葫蘆畫瓢:

1.  driver/video/Kconfig:

config FB_CBP
 tristate "VIA(VTC) CBP LCD framebuffer support"
 depends on FB && ARCH_CBP
 select FB_CFB_FILLRECT
 select FB_CFB_COPYAREA
 select FB_CFB_IMAGEBLIT
    ---help---
      Frame Buffer Driver for VIA Telecom(VTC) CBP chipset.

其中的FB_CFB_XX是爲了將CFB相關的函數編譯進去,相當於軟件對畫框等操作進行加速


2. driver/video/Makefile 

obj-$(CONFIG_FB_CBP)               +=cbp-fb.o

    第二步當然是把這個文件改改,一方面把那些名字都替換成俺喜歡的名字,其次只好還要能夠編譯過,無非就是修修補補,這個比較容易。

 

3.修改跟EVB相關的參數

      主要是修改分辨率,修改RGB565的bit定義等等,就是修改傳說中的fix和var參數

static struct fb_fix_screeninfo cbp_fb_fix __initdata = {
 .id  = "cbp",
 .smem_len = 240*320*2,
 .type  = FB_TYPE_PACKED_PIXELS,
 .visual  = FB_VISUAL_TRUECOLOR,
 .line_length = 240*2,
 .accel  = FB_ACCEL_NONE,
};

static struct fb_var_screeninfo cbp_fb_var __initdata = {
 .xres  = 240,
 .yres  = 320,
 .xres_virtual = 240,
 .yres_virtual = 320,
 .bits_per_pixel = 16,
    .red  = {11, 5, 0},
 .green  = {5, 6, 0},
 .blue  = {0, 5, 0},
 .activate = FB_ACTIVATE_NOW,
 .height  = -1,
 .width  = -1,
 .vmode  = FB_VMODE_NONINTERLACED,
};

4.爲驅動分配內存 

       現在這個世道,沒有Money甚嗎都幹不了,就像Frame Buffer驅動沒有內存一樣。當系統調用cbp_fb_init中的platform_xxx函數的時候已經註定後面要調用的第一個函數就是probe函數了。先調用以下函數:

 info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);

 緊接着申請顯示緩存,沒錯,就是顯存了,俺們這個系統不是獨立顯存,還得和CPU共享。分配的時候當然要分配一段沒有Cache的區域了,不然當使用CPU刷新屏幕的時候很可能會是這裏一個小黑條,那裏一片花條,這個是俺多年與CPU,GFX,DMA,CACHE打交道的經驗了。

     cbp_fb_fix.smem_start = dma_alloc_writecombine(&(dev->dev),
                                                    map_size,
                                                    &map_dma,
                                                    GFP_KERNEL);
這個函數的返回值就是申請到的地址,虛擬的。物理的存在那個map_dma裏面。

既然已經有了info這個筐,又有了顯存地址、fix info、var info這一堆東東,趕緊往裏面裝吧。

 info->var = cbp_fb_var;
 info->fix = cbp_fb_fix;
 info->fbops = &cbp_fb_ops;
 info->flags = FBINFO_DEFAULT;  /* not as module for now */
 info->pseudo_palette = info->par;
 info->par = NULL;
 info->screen_base = (char *) cbp_fb_fix.smem_start;

4.註冊
現在萬事具備,陸毅也給周瑜借來了東風,調用Color Map和Register函數即可:

 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
  framebuffer_release(info);
  return -ENOMEM;
 }

 //master_outb(3, DISPLAY_CONTROL_REG);

 if (register_framebuffer(info) < 0) {
  printk(KERN_ERR "Unable to register cbp frame buffer/n");
  fb_dealloc_cmap(&info->cmap);
  framebuffer_release(info);
  return -EINVAL;
 }
 return 0;

現在我可以打保票說,這個Frame Buffer驅動已經呱呱墜地OK了,其實Frame Buffer驅動一點都不復雜,是那些寫書的人把它寫複雜了,不過我的啓蒙教材ldd2和它的後續好像根本不寫Frame Buffer。或許就是覺得它太簡單。。。。。。。。?!

 

不過要讓這個驅動產生點實際的效果,比如顯示俺們那熟悉的可愛的小企鵝哦,還得明天繼續分解。

 

備註:

      我的前任臺灣老闆,一個賣液晶的朋友(注:兩個人,男的)告訴我,那種不帶LCD控制器的液晶面板叫玻璃,也就是LCD,就是隻有帶液晶控制器的MCU才能和它們對接,比如大家猛漢S3C2410,這些玻璃的掃描時序有MCU產生,因此MCU要不停的刷,會佔用很多的Memory帶寬。 而自己帶LCD控制器的叫LCM,也就是LCD Module,俗稱模組了,中發電子市場那種黑白的後面有綠色電路板12864模塊就是典型,不過現在很多也沒有後面背的綠色電路板了,芯片直接坐在玻璃上,俗稱COG,就是Chip On Glass了,是不是很土?而且很多模組都是彩色的,比如俺用的,深圳無名氏所產的以ILI932x作爲控制器的240x320彩色模組。模組的好處就是像51單片機這種帶寬吃緊的MCU,或者說跟S3C2410相比帶寬可以忽略的處理器可以接這種液晶,顯示點控制信息啥的。而像Samsung這種豪門,反正賣芯片就是賣沙子,幫客戶把LCD控制器做裏面了,客戶只用買玻璃就OK了,反而可以爲客戶節省成本。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章