S3C2440 linux LCD驅動分析
環境: 硬體平臺 TQ2440 東華3.5 inch TFT LCD
linux-2.6.30.4
1. LCD工作的硬體需求:
要使一塊LCD正常的顯示文字或影象,不僅需要LCD驅動器,而且還需要相應的LCD控制器。在通常情況下,生產廠商把LCD驅動器會以COF/COG的形式與LCD玻璃基板製作在一起,而LCD控制器則是由外部的電路來實現,現在很多的MCU內部都集成了LCD控制器,如S3C2410/2440等。通過LCD控制器就可以產生LCD驅動器所需要的控制訊號來控制STN/TFT屏了。
2. S3C2440內部LCD控制器結構圖:
我們根據資料手冊來描述一下這個整合在S3C2440內部的LCD控制器:
a:LCD控制器由REGBANK、LCDCDMA、TIMEGEN、VIDPRCS暫存器組成;
b:REGBANK由17個可程式設計的暫存器組和一塊256*16的調色盤記憶體組成,它們用來配置LCD控制器的;
c:LCDCDMA是一個專用的DMA,它能自動地把在偵記憶體中的視訊資料傳送到LCD驅動器,通過使用這個DMA通道,視訊資料在不需要CPU的干預的情況下顯示在LCD屏上;
d:VIDPRCS接收來自LCDCDMA的資料,將資料轉換為合適的資料格式,比如說4/8位單掃,4位雙掃顯示模式,然後通過資料埠VD[23:0]傳送視訊資料到LCD驅動器;
e:TIMEGEN由可程式設計的邏輯組成,他生成LCD驅動器需要的控制訊號,比如VSYNC、HSYNC、VCLK和LEND等等,而這些控制訊號又與REGBANK暫存器組中的LCDCON1/2/3/4/5的配置密切相關,通過不同的配置,TIMEGEN就能產生這些訊號的不同形態,從而支援不同的LCD驅動器(即不同的STN/TFT屏)。
3. 常見TFT屏工作時序分析:
LCD提供的外部介面訊號:
|
所有顯示器顯示影象的原理都是從上到下,從左到右的。這是什麼意思呢?這麼說吧,一副影象可以看做是一個矩形,由很多排列整齊的點一行一行組成,這些點稱之為畫素。那麼這幅圖在LCD上的顯示原理就是:
|
上面時序圖上各時鐘延時引數的含義如下:(這些引數的值,LCD產生廠商會提供相應的資料手冊)
|
對於以上這些引數的值將分別儲存到REGBANK暫存器組中的LCDCON1/2/3/4/5暫存器中:(對暫存器的操作請檢視S3c2440資料手冊LCD部分)
|
4. 幀緩衝(FrameBuffer):
幀緩衝是Linux為顯示裝置提供的一個介面,它把一些顯示裝置描述成一個緩衝區,允許應用程式通過 FrameBuffer定義好的介面訪問這些圖形裝置,從而不用去關心具體的硬體細節。對於幀緩衝裝置而言,只要在顯示緩衝區與顯示點對應的區域寫入顏色值,對應的顏色就會自動的在螢幕上顯示。下面來看一下在不同色位模式下緩衝區與顯示點的對應關係:
幀緩衝(FrameBuffer)裝置驅動 :
幀緩衝裝置為標準的字元型裝置,在Linux中主裝置號29,定義在/include/linux/major.h中的FB_MAJOR,次裝置號定義幀緩衝的個數,最大允許有32個FrameBuffer,定義在/include/linux/fb.h中的FB_MAX,對應於檔案系統下/dev /fb%d裝置檔案。
1. 幀緩衝裝置驅動在Linux子系統中的結構如下:
我們從上面這幅圖看,幀緩衝裝置在Linux中也可以看做是一個完整的子系統,大體由fbmem.c和xxxfb.c組成。向上給應用程式提供完善的裝置檔案操作介面(即對FrameBuffer裝置進行read、write、ioctl等操作),介面在Linux提供的fbmem.c檔案中實現;向下提供了硬體操作的介面,只是這些介面Linux並沒有提供實現,因為這要根據具體的LCD控制器硬體進行設定,所以這就是我們要做的事情了(即xxxfb.c 部分的實現)。
2. 幀緩衝相關的重要資料結構:
從幀緩衝裝置驅動程式結構看,該驅動主要跟fb_info結構體有關,該結構體記錄了幀緩衝裝置的全部資訊,包括裝置的設定引數、狀態以及對底層硬體操作的函式指標。在Linux 中,每一個幀緩衝裝置都必須對應一個fb_info,fb_info在/linux/fb.h中的定義如下:(只列出重要的一些)
|
其中,比較重要的成員有struct fb_var_screeninfo var、struct fb_fix_screeninfo fix和struct fb_ops *fbops,他們也都是結構體。下面我們一個一個的來看。
fb_var_screeninfo結構體主要記錄使用者可以修改的控制器的引數,比如螢幕的解析度和每個畫素的位元數等,該結構體定義如下:
|
而fb_fix_screeninfo結構體又主要記錄使用者不可以修改的控制器的引數,比如螢幕緩衝區的實體地址和長度等,該結構體的定義如下:
|
fb_ops結構體是對底層硬體操作的函式指標,該結構體中定義了對硬體的操作有:(這裡只列出了常用的操作)
|
3. 幀緩衝裝置作為平臺裝置:
在S3C2440中,LCD控制器被整合在晶片的內部作為一個相對獨立的單元,所以Linux把它看做是一個平臺裝置,故在核心程式碼/arch/arm/plat-s3c24xx/devs.c 中定義有LCD相關的平臺裝置及資源,程式碼如下:
除此之外,Linux還在/arch/arm/mach-s3c2410/include/mach/fb.h中為LCD平臺裝置定義了一個 s3c2410fb_mach_info結構體,該結構體主要是記錄LCD的硬體引數資訊(比如該結構體的s3c2410fb_display成員結構中就用於記錄LCD的螢幕尺寸、螢幕資訊、可變的螢幕引數、LCD配置暫存器等),這樣在寫驅動的時候就直接使用這個結構體。
struct s3c2410fb_hw {
unsigned long lcdcon1;
unsigned long lcdcon2;
unsigned long lcdcon3;
unsigned long lcdcon4;
unsigned long lcdcon5;
};
/* LCD description */
struct s3c2410fb_display {
/* LCD type */
unsigned type;
/* Screen size */
unsigned short width;
unsigned short height;
/* Screen info */
unsigned short xres;
unsigned short yres;
unsigned short bpp;
unsigned pixclock; /* pixclock in picoseconds */
unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */
/* lcd configuration registers */
unsigned long lcdcon5;
};
struct s3c2410fb_mach_info {
struct s3c2410fb_display *displays; /* attached diplays info */
unsigned num_displays; /* number of defined displays */
unsigned default_display;
/* GPIOs */
unsigned long gpcup;
unsigned long gpcup_mask;
unsigned long gpccon;
unsigned long gpccon_mask;
unsigned long gpdup;
unsigned long gpdup_mask;
unsigned long gpdcon;
unsigned long gpdcon_mask;
/* lpc3600 control register */
unsigned long lpcsel;
};
下面,我們來看一下核心是如果使用這個結構體的。在/arch/arm/mach-s3c2440/mach-smdk2440.c 中定義有:
|
從上面的程式碼來看,要使LCD控制器支援其他的LCD屏,重要的是根據LCD的資料手冊修改以上這些引數的值。下面,我們再看一下在驅動中是如果引用到 s3c2410fb_mach_info結構體的(注意上面講的是在核心中如何使用的)。在mach-smdk2440.c中有:
轉載出處:https://blog.csdn.net/tiangwan2011/article/details/7549746
|
s3c24xx_fb_set_platdata定義在 plat-s3c24xx/devs.c中:
|