上次說到,小企鵝終於可以顯示了,但是現在這個世道,現在這個中國,山寨橫行,沒有最便宜的,只有更便宜的,今天用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了。請問該去兜風了嗎,我的勞力士呢?原來在水裏,離兜風時間還有三個小時呢!