爲EVB添加Frame Buffer驅動(三):讓驅動更兼容

     上次說到,小企鵝終於可以顯示了,但是現在這個世道,現在這個中國,山寨橫行,沒有最便宜的,只有更便宜的,今天用ILI9320的人,或許就是昨天用S6D0110,或許還是明天用和諧8347的人,不好意思是HX8347,這個可惡的輸入法。因此,俺們的驅動就不能只支持ILI9320,不然客戶就用別人的芯片去了。當然,客戶也可以直接改cbp-fb.c或者cbp-fb.h, 可是客戶是很忙的,說不定今天晚上還要去兜風呢!而且客戶也不想知道,我們ASIC老大們也不想讓他知道俺們的DMA和其他模塊是怎麼玩的,所以把故意把文檔寫的那麼晦澀,連我們這些本公司開發人員都看不懂。客戶可能改了還可能會出新的bug,還得麻煩俺們。

    因此對於LCD,就定義一個結構來描述它算了,爲了不要太複雜,就定義了這些參數:

typedef struct LCD_INFO
{
    int16 BankNo;                   /*Physical LCD/IF Bank Number*/
    int16 FreezeStatus;                    /*Lcd Freeze State*/ 
    void (*FreezeCallback)(void *pInfo);   /*Callback function when lcd in freezed state*/
    int   LcdOnState;                      /*Lcd is on or sleep*/
    SemaphoreT *SemaphoreCbP;           /*Lcd Device Seamphore*/
    SemaphoreT *FrameBufferSemaphoreCbP;           /*Lcd Device Seamphore*/
   LcdBankAddressT Address;           /*Bank Cmd and Data Address*/
   LcdDMAControlT DMAControl;             /*DMA Information*/
  struct LCD_CONTROLLER
  {
      LcdBankParamT BankParam; /*Bank Timing*/
      HwdLcdInfoT  LcdInfo;  /*Lcd information about vendor,size,framebuffer,etc*/
     void (*InitDev)(struct LCD_INFO *Info);
     void (*SetWindow)(struct LCD_INFO *pInfo,uint16 x, uint16 y, uint16 dx, uint16 dy);
     oid (*UpdateRect)(struct LCD_INFO *pInfo,uint8* Bmp, uint16 x, uint16 y, uint16 dx, uint16 dy);
     oid (*UpdateAll)(struct LCD_INFO *pInfo,uint8* Bmp, uint16 x, uint16 y, uint16 dx, uint16 dy);
     oid (*SetContrast)(struct LCD_INFO *pInfo,uint8 Leve);
     oid (*LcdOn)(struct LCD_INFO *pInfo,bool OpCode);
  }*pController;
}LcdInfoT;

其實看起來還是挺複雜的,其中的LCD_CONTROLLER定義是相對於具體的LCD控制器的,其實就算有了S3C2410那樣的帶控制器的CPU,也是可以用這個結構的。LCD_CONTROLLER的 HwdLcdInfoT  LcdInfo裏面則主要定義了一些和LCD的參數有關的東東,比如分辨率,顏色深度之類的玩意兒。LCD_CONTROLLER還定義了幾個操作,就是UpdateRect之類的東東。

   剩下的其他成員主要定義了一些防止競態訪問的Semaphore,各種狀態控制,還有一個就是關於我們的DMA的參數。

  這樣對於客戶就簡單了,就算他今天晚上除了去兜風還要泡吧也沒關係了,因爲他只需要負責其中的LCD_CONTROLLER結構就OK了,比如如下的ILI9320定義:

LcdControllerInfoT gILI9320_16BitBus_16BPP=
{
 {
  LCDIF_READ_WAIT(0x1)|LCDIF_READ_HIGH(1),/*Read Timing*/
  LCDIF_WRITE_WAIT(0x2)|LCDIF_WRITE_HIGH(2),/*Write Timing*/
  LCDIF_MODE_CONVMODE(LCD_CONV_NONE)|LCDIF_MODE_DATAWIDTH(LCD_BUS_WIDTH_16Bit)
 },
 {
  "ILI",      /*Vendor*/
   "9320",     /*Model*/
  240,      /*Width*/
  320,      /*Height*/
  FB_16BPP,      /*Frame buffer BPP*/
  NULL      /*Frame buffer Address*/
 },
 /*****Operations********/
 ILI9320Init,    /*InitDev*/
 ILI9320WindowSet,   /*Set Window address*/
 ILI9320UpdateRect,   /*UpdateRect*/
 ILI9320UpdateAll,     /*UpdateAll*/
 ILI9320SetContrast,  /*Set Contrast*/
 ILI9320LcdOn    /*LCD on/off*/
};

Operations以前的東西看起來很長,其實第一對大括號就是配置一下LCD Bridge應該以什麼樣的時序與LCD Controller接口,其中的第三行表示是顏色變換和外部總線寬度等等。

第二個大括號就更簡單了,有廠商名字,控制器型號,寬度,長寬和顏色深度,FrameBuffer地址是個Legacy,現在由驅動程序申請,因此在這裏就是NULL了,當然也可以設上,不過設了也是白設!

剩下就是Operations了,看名字就知道是幹啥的,這個東西在俺們的平臺上都是有用的,比如Update Rect之類的東東,但是在Linux Frame Buffer上就沒用了,因爲Frame Buffer驅動都是在內存中操作,有CFB支持,這些設置硬件的操作就不需要了。而且Update在Linux裏面都是定時刷新的,也不需要專門的Update函數了。

因此俺的客戶就只需要實現 ILI9320Init,ILI9320SetContrast,ILI9320LcdOn,如果不需要調亮度和關閉LCD的話,他就只剩下ILI9320Init一個函數需要寫了,聽起來好像還是有點麻煩,其實每個LCM廠商都會給初始化參數的,如下:

Cmd(0x1234);

Data(0x4321);

這樣的東東。

你只要按部就班的填完就OK了。請問該去兜風了嗎,我的勞力士呢?原來在水裏,離兜風時間還有三個小時呢!

 

 

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