为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了。请问该去兜风了吗,我的劳力士呢?原来在水里,离兜风时间还有三个小时呢!

 

 

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