版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、S3C2440 上 LCD 驅(qū)動(dòng)(FrameBuffer)實(shí)例開(kāi)發(fā)講解一、開(kāi)發(fā)環(huán)境主 機(jī):VMWare-Fedora 9開(kāi)發(fā)板:Mini2440-64MB Nand, Kernel:編譯器:arm-linux-gcc-4.3.2二、背景知識(shí)1. LCD 工作的硬件需求:要使一塊 LCD 正常的顯示文字或圖像,不僅需要 LCD 驅(qū)動(dòng)器,而且還需要相應(yīng)的 LCD 控制器在通常情況下,生產(chǎn)廠商把 LCD 驅(qū)動(dòng)器會(huì)以 COF/COG 的形式與 LCD 玻璃基板制作在一起,而 LCD 控制器則是由外部的電路來(lái)實(shí)現(xiàn),現(xiàn)在很多的 MCU都集成了 LCD 控制器,如 S3C2410/2440 等 通過(guò) LCD
2、控制器就可以產(chǎn)生 LCD 驅(qū)動(dòng)器所需要的控制信號(hào)來(lái)控制 SFT 屏了2. S3C2440LCD 控制器結(jié)構(gòu)圖:來(lái)描述一下這個(gè)集成在 S3C2440的 LCD 控制器:根據(jù)a:LCD 控制器由 REGB成;、LCDCDMA、TIMEGEN、VIDPRCS 寄存器組b:REGB由 17 個(gè)可編程的寄存器組和一塊 256*16 的調(diào)色板內(nèi)存組成,它們用來(lái)配置 LCD 控制器的;c:LCDCDMA 是一個(gè)的 DMA,它能自動(dòng)地把在偵內(nèi)存中的數(shù)據(jù)傳送到 LCD 驅(qū)動(dòng)器,通過(guò)使用這個(gè) DMA 通道,況下顯示在 LCD 屏上;數(shù)據(jù)在不需要 CPU 的干預(yù)的情d:VIDPRCS 接收來(lái)自 LCDCDMA 的數(shù)
3、據(jù),將數(shù)據(jù)轉(zhuǎn)換為合適的數(shù)據(jù)格式,比如說(shuō) 4/8 位單掃,4據(jù)到 LCD 驅(qū)動(dòng)器;掃顯示模式,然后通過(guò)數(shù)據(jù)端口 VD23:0傳送數(shù)e:TIMEGEN 由可編程的邏輯組成,他生成 LCD 驅(qū)動(dòng)器需要的控制信號(hào),比如VSYNC、HSYNC、VCLK 和 LEND 等等,而這些控制信號(hào)又與 REGB寄存器組中的 LCDCON1/2/3/4/5 的配置密切相關(guān),通過(guò)不同的配置,TIMEGEN就能產(chǎn)生這些信號(hào)的不同形態(tài),從而支持不同的 LCD 驅(qū)動(dòng)器(即不同的SFT 屏)3.常見(jiàn) TFT 屏工作時(shí)序分析:LCD 提供的外部接口信號(hào):VSYNC/VFRAME/STV:垂直同步信號(hào)(TFT)/幀同步信號(hào)(ST
4、N)/SEC TFT 信號(hào); HSYNC/VLINE/CPV:水平同步信號(hào)(TFT)/行同步脈沖信號(hào)(STN)/SEC TFT 信號(hào);VCLK/LCD_HCLK:象素時(shí)鐘信號(hào)(TFT/STN)/SEC TFT 信號(hào); VD23:0:LCD 像素?cái)?shù)據(jù)輸出端口(TFT/STN/SEC TFT);VDEN/VM/TP:數(shù)據(jù)使能信號(hào)(TFT)/LCD 驅(qū)動(dòng)交流偏置信號(hào)(STN)/SEC TFT 信號(hào);所有顯示器顯示圖像的原理都是從上到下,從左到右的 這是什么意思呢?這么說(shuō)吧,一副圖像可以看做是一個(gè)矩形,由很多排列整齊的點(diǎn)一行一行組成,這些點(diǎn)稱之為像素 那么這幅圖在 LCD 上的顯示原理就是:上面時(shí)序圖
5、上各時(shí)鐘延時(shí)參數(shù)的含義如下:(這些參數(shù)的值,LCD 產(chǎn)生廠商會(huì)提)供相應(yīng)的VBPD(vertical back porch):表示在一幀圖像開(kāi)始時(shí),垂直同步信號(hào)以后的無(wú)效的行數(shù),對(duì)應(yīng)驅(qū)動(dòng)中的 upper_margin;VFBD(vertical front porch):表示在一幀圖像結(jié)束后,垂直同步信號(hào)以A:顯示指針從矩形左上角的第一行第一個(gè)點(diǎn)開(kāi)始,一個(gè)點(diǎn)一個(gè)點(diǎn)的在 LCD上顯示,在上面的時(shí)序圖上用時(shí)間線表示就為 VCLK, 稱之為像素時(shí)鐘信號(hào);B:當(dāng)顯示指針一直顯示到矩形的右邊就結(jié)束這一行,那么這一行的動(dòng)作在上面的時(shí)序圖中就稱之為 1 Line;C:接下來(lái)顯示指針又回到矩形的左邊從第二行開(kāi)
6、始顯示,注意,顯示指針在從第一行的右邊回到第二行的左邊是需要一定的時(shí)間的, 稱之為行切換;D:如此類推,顯示指針就這樣一行一行的顯示至矩形的右下角才把一副圖顯示完成 因此,這一行一行的顯示在時(shí)間線上看,就是時(shí)序圖上的 HSYNC; E:然而,LCD 的顯示并不是對(duì)一副圖像快速的顯示一下,為了持續(xù)和穩(wěn)定的在 LCD 上顯示,就需要切換到另一幅圖上(另一幅圖可以和上一副圖一樣或者不一樣,目的只是為了將圖像持續(xù)的顯示在 LCD 上) 那么這一副一副的圖像就稱之為幀,在時(shí)序圖上就表示為 1 Frame,因此從時(shí)序圖上可以看出 1 Line 只是 1 Frame 中的一行;F:同樣的,在幀與幀切換之間也
7、是需要一定的時(shí)間的,稱之為幀切換,那么 LCD 整個(gè)顯示的過(guò)程在時(shí)間線上看,就可表示為時(shí)序圖上的 VSYNCLEND/STH:行結(jié)束信號(hào)(TFT)/SEC TFT 信號(hào); LCD_LPCOE:SEC TFT OE 信號(hào); LCD_LPCREV:SEC TFT REV 信號(hào); LCD_LPCREVB:SEC TFT REVB 信號(hào)對(duì)于以上這些參數(shù)的值將分別保存到 REGB寄存器組中的LCDCON1/2/3/4/5 寄存器中:(對(duì)寄存器的操作請(qǐng)查看 S3c2440 LCD 部分)4. 幀緩沖(FrameBuffer):LCDCON1:17 - 8 位 CLKVAL6 - 5 位掃描模式(對(duì)于 ST
8、N 屏:4 位單/雙掃、8 位單掃)4 - 1 位色位模式(1BPP、8BPP、16BPP 等)LCDCON2:31 - 24 位 VBPD 23 - 14 位 LINEVAL13 - 6 位 VFPD5 - 0 位 VSPWLCDCON3:25 - 19 位 HBPD 18 - 8 位 HOZVAL7 - 0 位 HFPDLCDCON4: 7 - 0 位 HSPWLCDCON5:前的無(wú)效的行數(shù),對(duì)應(yīng)驅(qū)動(dòng)中的 lower_margin;VSPW(vertical sync pulse width):表示垂直同步脈沖的寬度,用行數(shù)計(jì)算,對(duì)應(yīng)驅(qū)動(dòng)中的 vsync_len;HBPD(horizont
9、al back porch):表示從水平同步信號(hào)開(kāi)始到一行的有效數(shù)據(jù)開(kāi)始之間的 VCLK 的個(gè)數(shù),對(duì)應(yīng)驅(qū)動(dòng)中的 left_margin; HFPD(horizontal front porth):表示一行的有效數(shù)據(jù)結(jié)束到下一個(gè)水平同步信號(hào)開(kāi)始之間的 VCLK 的個(gè)數(shù),對(duì)應(yīng)驅(qū)動(dòng)中的 right_margin; HSPW(horizontal sync pulse width):表示水平同步信號(hào)的寬度,用 VCLK計(jì)算,對(duì)應(yīng)驅(qū)動(dòng)中的 hsync_len;幀緩沖是 Linux 為顯示設(shè)備提供的一個(gè)接口,它把一些顯示設(shè)備描述成一個(gè)緩沖區(qū),允許應(yīng)用程序通過(guò) FrameBuffer 定義好的接口這些圖形設(shè)
10、備,從而不用去關(guān)心具體的硬件細(xì)節(jié) 對(duì)于幀緩沖設(shè)備而言,只要在顯示緩沖區(qū)與顯示點(diǎn)對(duì)應(yīng)的區(qū)域?qū)懭腩伾?,?duì)應(yīng)的顏色就會(huì)自動(dòng)的在屏幕上顯示 下面來(lái)看一下在不同色位模式下緩沖區(qū)與顯示點(diǎn)的對(duì)應(yīng)關(guān)系:三、幀緩沖(FrameBuffer)設(shè)備驅(qū)動(dòng)結(jié)構(gòu):幀緩沖設(shè)備為標(biāo)準(zhǔn)的字符型設(shè)備,在 Linux 中主設(shè)備號(hào) 29,定義在/include/linux/major.h 中的 FB_MAJOR,次設(shè)備號(hào)定義幀緩沖的個(gè)數(shù),最大允許有 32 個(gè) FrameBuffer,定義在/include/linux/fb.h 中的 FB_MAX,對(duì)應(yīng)件系統(tǒng)下/dev/fb%d 設(shè)備文件1.幀緩沖設(shè)備驅(qū)動(dòng)在 Linux 子系統(tǒng)中的
11、結(jié)構(gòu)如下:從上面這幅圖看,幀緩沖設(shè)備在 Linux 中也可以看做是一個(gè)完整的子系統(tǒng),大體由 fbmem.c 和fb.c 組成 向上給應(yīng)用程序提供完善的設(shè)備文件操作接口(即對(duì) FrameBuffer 設(shè)備進(jìn)行 read、write、ioctl 等操作),接口在 Linux 提供的 fbmem.c 文件中實(shí)現(xiàn);向下提供了硬件操作的接口,只是這些接口 Linux 并沒(méi)有提供實(shí)現(xiàn),因?yàn)檫@要根據(jù)具體的 LCD 控制器硬件進(jìn)行設(shè)置,所以這就是要做的事情了(即fb.c 部分的實(shí)現(xiàn))2. 幀緩沖相關(guān)的重要數(shù)據(jù)結(jié)構(gòu):從幀緩沖設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)看,該驅(qū)動(dòng)主要跟 fb_info 結(jié)構(gòu)體有關(guān),該結(jié)構(gòu)體了幀緩沖設(shè)備的全部
12、信息,包括設(shè)備的設(shè)置參數(shù)、狀態(tài)以及對(duì)底層硬件操作的函數(shù)指針 在Linux 中,每一個(gè)幀緩沖設(shè)備都必須對(duì)應(yīng)一個(gè) fb_info,fb_info在/linux/fb.h 中的定義如下:(只列出重要的一些)struct fb_info node;flags;struct fb_var_screeninfo var;/*LCD 可變參數(shù)結(jié)構(gòu)體*/ struct fb_fix_screeninfo fix;/*LCD 固定參數(shù)結(jié)構(gòu)體*/ struct fb_monspecs monspecs; /*LCD 顯示器標(biāo)準(zhǔn)*/ struct work_struct queue;/*幀緩沖事件隊(duì)列*/struc
13、t fb_pixmap pixmap;/*圖像硬件 mapper*/ struct fb_pixmap sprite;/*光標(biāo)硬件 mapper*/ struct fb_cmap cmap; /*當(dāng)前的顏色表*/ struct fb_mode *mode; /*當(dāng)前的顯示模式*/#ifdef CONFIG_FB_BACKLIGHTstruct backlight_device *bl_dev;/*對(duì)應(yīng)的背光設(shè)備*/ struct mutex bl_curve_mutex;u8 bl_curveFB_BACKLIGHT_LEVELS;/*背光調(diào)整*/ #endif#ifdef CONFIG_FB
14、_DEFERRED_IOstruct delayed_work deferred_work; struct fb_deferred_io *fbdefio;#endifstruct fb_ops *fbops; /*對(duì)底層硬件操作的函數(shù)指針*/ struct device *device;struct device *dev; /*fb 設(shè)備*/ class_flag;#ifdef CONFIG_FB_TILITTINGstruct fb_tile_ops *tileops; /*圖塊 Blitting*/ #endifchar iomem *screen_base; /*虛擬址*/unsig
15、ned long screen_size; /*LCD IO的虛擬內(nèi)存大小*/其中,比較重要的成員有 struct fb_var_screeninfo var、struct fb_fix_screeninfo fix 和 struct fb_ops *fbops,他們也都是結(jié)構(gòu)體下面我們一個(gè)一個(gè)的來(lái)看fb_var_screeninfo 結(jié)構(gòu)體主要用戶可以修改的控制器的參數(shù),比如屏幕的分辨率和每個(gè)像素的比特?cái)?shù)等,該結(jié)構(gòu)體定義如下:struct fb_var_screeninfo u32 xres;/*可見(jiàn)屏幕一行有多少個(gè)像素點(diǎn)*/ u32 yres;/*可見(jiàn)屏幕一列有多少個(gè)像素點(diǎn)*/ u32 x
16、res_virtual;/*虛擬屏幕一行有多少個(gè)像素點(diǎn)*/ u32 yres_virtual;/*虛擬屏幕一列有多少個(gè)像素點(diǎn)*/ u32 xoffset;/*虛擬到可見(jiàn)屏幕之間的行偏移*/ u32 yoffset;/*虛擬到可見(jiàn)屏幕之間的列偏移*/ u32 bits_per_pixel;/*每個(gè)像素的位數(shù)即 BPP*/ u32 grayscale;/*非 0 時(shí),指的是灰度*/struct fb_bitfield red;/*fb 緩存的 R 位域*/ struct fb_bitfield green; /*fb 緩存的 G 位域*/ struct fb_bitfield blue; /*fb
17、 緩存的 B 位域*/ struct fb_bitfield transp; /*/ u32 nonstd;/* != 0 非標(biāo)準(zhǔn)像素格式*/ u32 activate;void *pseudo_palette;/*偽 16 色顏色表*/ #define FBINFO_SE_RUNNING0 #define FBINFO_SE_SUSPENDED 1u32 se; /*LCD 的掛起或恢復(fù)狀態(tài)*/ void *fbcon_par;void *par;而 fb_fix_screeninfo 結(jié)構(gòu)體又主要用戶不可以修改的控制器的參數(shù),比如屏幕緩沖區(qū)的物理地址和長(zhǎng)度等,該結(jié)構(gòu)體的定義如下:struc
18、t fb_fix_screeninfo char id16;/*字符串形式的標(biāo)示符 */ unsigned long smem_start; /*fb 緩存的開(kāi)始位置 */ u32 smem_len;/*fb 緩存的長(zhǎng)度 */ u32 type;/*看 FB_TYPE_* */ u32 type_aux;/*分界*/ u32 visual;/*看 FB_VISUAL_* */ u16 xpanstep;/*如果沒(méi)有硬件 panning 就賦值為 0 */ u16 ypanstep;/*如果沒(méi)有硬件 panning 就賦值為 0 */ u32 height;/*高度*/ u32 width;/*
19、寬度*/ u32 accel_flags;/*定時(shí):除了 pixclock 本身外,其他的都以像素時(shí)鐘為*/ u32 pixclock;/*像素時(shí)鐘(皮秒)*/ u32 left_margin;/*行切換,從同步到繪圖之間的延遲*/ u32 right_margin;/*行切換,從繪圖到同步之間的延遲*/ u32 upper_margin;/*幀切換,從同步到繪圖之間的延遲*/ u32 lower_margin;/*幀切換,從繪圖到同步之間的延遲*/ u32 hsync_len;/*水平同步的長(zhǎng)度*/ u32 vsync_len;/*垂直同步的長(zhǎng)度*/ u32 sync; u32 vmode;
20、 u32 roe; u325;/*保留*/;fb_ops 結(jié)構(gòu)體是對(duì)底層硬件操作的函數(shù)指針,該結(jié)構(gòu)體中定義了對(duì)硬件的操作有:(這里只列出了常用的操作)struct fb_ops struct module *owner;/檢查可變參數(shù)并進(jìn)行設(shè)置(*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);/根據(jù)設(shè)置的值進(jìn)行更新,使之有效 (*fb_set_par)(struct fb_info *info);/設(shè)置顏色寄存器(*fb_setcolreg)(unsigned regno, unsigned red, un
21、signed green, unsigned blue, unsigned transp, struct fb_info *info);/顯示空白(*fb_bl)(bl, struct fb_info *info);/矩形填充void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); u16 ywrapstep;/*如果沒(méi)有硬件 ywrap 就賦值為 0 */ u32 line_length;/*一行的字節(jié)數(shù) */unsigned long mmio_start; /*內(nèi)存IO 的開(kāi)始位置*/ u32
22、mmio_len;/*內(nèi)存IO 的長(zhǎng)度*/ u32 accel; u163;/*保留*/;3. 幀緩沖設(shè)備作為設(shè)備:在 S3C2440 中,LCD 控制器被集成在的作為一個(gè)相對(duì)獨(dú)立的單元,所以 Linux 把它看做是一個(gè)設(shè)備,故在內(nèi)核代碼/arch/arm/plat-s3c24xx/devs.c 中定義有 LCD 相關(guān)的下:設(shè)備及資源,代碼如/* LCD Controller */LCD 控制器的資源信息sic struct resour3c_lcd_resource = 0 = .start = S3C24XX_PA_LCD, /控制器 IO 端口開(kāi)始地址.end = S3C24XX_PA_
23、LCD + S3C24XX_SZ_LCD - 1,/控制器 IO 端口結(jié)束地址.flags = IORESOURCE_MEM,/標(biāo)識(shí)為 LCD 控制器 IO 端口,在驅(qū)動(dòng)中這個(gè)就表示IO 端口,1 = .start = IRQ_LCD,/LCD 中斷.end = IRQ_LCD,.flags = IORESOURCE_IRQ,/標(biāo)識(shí)為 LCD 中斷;/數(shù)據(jù)void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);/圖形填充void (*fb_imageblit) (struct fb_info *i
24、nfo, const struct fb_image *image);除此之外,Linux 還在/arch/arm/mach-s3c2410/include/mach/fb.h 中為L(zhǎng)CD設(shè)備定義了一個(gè) s3c2410fb_mach_info 結(jié)構(gòu)體,該結(jié)構(gòu)體主要是硬件參數(shù)信息(比如該結(jié)構(gòu)體的 s3c2410fb_display 成員結(jié)構(gòu)中就用于LCD 的 LCD的屏幕尺寸、屏幕信息、可變的屏幕參數(shù)、LCD 配置寄存器等),這樣在寫(xiě)驅(qū)動(dòng)的時(shí)候就直接使用這個(gè)結(jié)構(gòu)體 下面,來(lái)看一下內(nèi)核是如果使用這個(gè)結(jié)構(gòu)體的在/arch/arm/mach-s3c2440/mach-smdk2440.c 中定義有:/
25、* LCD driver info */LCD 硬件的配置信息,注意這里我使用的 LCD 是 NEC 3.5 寸 TFT 屏,這些參數(shù)要根據(jù)具體的 LCD 屏進(jìn)行設(shè)置sic struct s3c2410fb_display smdk2440_lcd_cfg initdata = /這個(gè)地方的設(shè)置是配置 LCD 寄存器 5,這些宏定義在 regs-lcd.h 中,計(jì)算后二進(jìn)制為:111111111111,然后對(duì)照 上 LCDCON5 的各位來(lái)看,注意是從右邊開(kāi)始.lcdcon5 = S3C2410_LCDCON5_FRM565 |sic u64 s3c_device_lcd_dmamask =
26、0 xffUL;struct platform_devi3c_device_lcd = .name= s3c2410-lcd,/作為設(shè)備的 LCD 設(shè)備名.id= -1,.num_resour= ARRAY_SIZE(s3c_lcd_resource),/資源數(shù)量.resource= s3c_lcd_resource,/上面定義的資源.dev = .dma_mask = &s3c_device_lcd_dmamask,.coherent_dma_mask = 0 xffUL;EXPORT_SYMBOL(s3c_device_lcd);/導(dǎo)出定義的 LCD設(shè)備,好在mach-smdk2440.c
27、 的 smdk2440_devi中添加到設(shè)備列表中S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,.type= S3C2410_LCDCON1_TFT,/TFT 類型/* NEC 3.5 */.width= 240,/屏幕寬度.height= 320,/屏幕高度/以下一些參數(shù)在上面的時(shí)序圖分析中講到過(guò),各參數(shù)的值請(qǐng)跟據(jù)具體的 LCD 屏結(jié)合上面時(shí)序分析來(lái)設(shè)定.pixclock= 100000,/像素時(shí)鐘.xres= 240,/水平可見(jiàn)的有效像
28、素.yres= 320,/垂直可見(jiàn)的有效像素.bpp= 16,/色位模式.left_margin = 19,/行切換,從同步到繪圖之間的延遲.right_margin = 36,/行切換,從繪圖到同步之間的延遲.hsync_len= 5,/水平同步的長(zhǎng)度.upper_margin = 1,/幀切換,從同步到繪圖之間的延遲.lower_margin = 5,/幀切換,從繪圖到同步之間的延遲.vsync_len= 1,/垂直同步的長(zhǎng)度;sic struct s3c2410fb_mach_info smdk2440_fb_info initdata = .displays= &smdk2440_lc
29、d_cfg,/應(yīng)用上面定義的配置信息.num_displays= 1,.default_display = 0,注意:可能有很多朋友不知道上面紅色部分的參數(shù)是做什么的,其值又是怎么設(shè)置的?其實(shí)它是跟你的開(kāi)發(fā)板 LCD 控制器密切相關(guān)的,看了下面兩幅圖相信就大概知道他們是干什么用的:.gpccon= 0 xaaaa555a,/將 GPC0、GPC1 配置成 LEND 和 VCLK,將 GPC8-15 配置成 VD0-7,其他配置成普通輸出 IO 口.gpccon_mask= 0 xff,.gpcup= 0 x0000f,/GPIOC 的上拉功能.gpcup_mask= 0 xff,.gpdcon
30、= 0 xaaaaaaaa,/將 GPD0-15 配置成 VD8-23.gpdcon_mask= 0 xff,.gpdup= 0 x0000f,/GPIOD 的上拉功能.gpdup_mask= 0 xff,.lpcsel= 0 x0,/這個(gè)是三星 TFT 屏的參數(shù),這里不用;上面第一幅圖是開(kāi)發(fā)板原理圖的 LCD 控制器部分,第二幅圖是 S3c2440 數(shù)據(jù)手冊(cè)中 IO 端口 C 和 IO 端口 D 控制器部分原理圖中使用了 GPC8-15 和 GPD0-15 來(lái)用做 LCD 控制器 VD0-VD23 的數(shù)據(jù)端口,又分別使用 GPC0、 GPC1 端口用做 LCD 控制器的 LEND 和 VCL
31、K 信號(hào),對(duì)于 GPC2-7 則是用做 STN 屏或者三星專業(yè) TFT 屏的相關(guān)信號(hào) 然而,S3C2440 的各個(gè) IO 口并不是單一的功能,都是復(fù)用端口,要使用他們首先要對(duì)他們進(jìn)行配置 所以上面紅色部分的參數(shù)就是把 GPC 和 GPD 的部分端口配置成 LCD 控制功能模式從以上講述的內(nèi)容來(lái)看,要使 LCD 控制器支持其他的 LCD 屏,重要的是根據(jù)LCD 的修改以上這些參數(shù)的值 下面,再看一下在驅(qū)動(dòng)中是如果引用到 s3c2410fb_mach_info 結(jié)構(gòu)體的(注意上面講的是在內(nèi)核中如何使用的) 在 mach-smdk2440.c 中有:/S3C2440 初始化函數(shù)sic void in
32、it smdk2440_machine_init(void)s3c24xx_fb_set_platdata 定義在 plat-s3c24xx/devs.c 中:這里再講一個(gè)小知識(shí):不知大家有沒(méi)有留意,在設(shè)備驅(qū)動(dòng)中,platform_data 可以保存各自設(shè)備實(shí)例的數(shù)據(jù),但這些數(shù)據(jù)的類型都是不同void init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)struct s3c2410fb_mach_info *npd;npd = kmalloc(sizeof(*npd), GFP_KERNEL); if (npd) memcpy
33、(npd, pd, sizeof(*npd);/這里就是將內(nèi)核中定義的 s3c2410fb_mach_info 結(jié)構(gòu)體數(shù)據(jù)保存到 LCD中,所以在寫(xiě)驅(qū)動(dòng)的時(shí)候就可以直接在中獲取 s3c2410fb_mach_info 結(jié)構(gòu)體的數(shù)據(jù)(即 LCD 各種參數(shù)信息)進(jìn)行操作s3c_device_lcd.dev.platform_data = npd; else prk(KERN_ERR no memory for LCD platform datan);/調(diào)用該函數(shù)將上面定義的 LCD 硬件信息保存到中s3c24xx_fb_set_platdata(&smdk2440_fb_info);s3c_i2c
34、0_set_platdata(NULL);platform_add_devi(smdk2440_devi, ARRAY_SIZE(smdk2440_devi);smdk_machine_init();的,為什么都可以保存?這就要看看 platform_data 的定義,定義在/linux/device.h 中,void *platform_data 是一個(gè) void 類型的指針,在 Linux中 void 可保存任何數(shù)據(jù)類型四、幀緩沖(FrameBuffer)設(shè)備驅(qū)動(dòng)實(shí)例代碼:、建立驅(qū)動(dòng)文件:my2440_lcd.c,依就是驅(qū)動(dòng)程序的最基本結(jié)構(gòu):FrameBuffer 驅(qū)動(dòng)的初始化和卸載部分及
35、其他,如下:#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*FrameBuffer 設(shè)備名稱*/sic char driver_name = my2440_lcd;/*定義一個(gè)結(jié)構(gòu)體用來(lái)驅(qū)動(dòng)程序中各函數(shù)中用到的變量先別看結(jié)構(gòu)體要定義這些成員,到各函數(shù)使用的地方就明白了*/ struct my2440f
36、b_varlcd_irq_no;/*保存 LCD 中斷號(hào)*/struct clk *lcd_clock;/*保存從鐘隊(duì)列中獲取的 LCD 時(shí)鐘*/struct resource *lcd_mem; /*LCD 的 IO 空間*/void iomem *lcd_base;/*LCD 的 IO 空間到虛擬地址*/ struct device *dev;struct s3c2410fb_hw regs; /*表示 5 個(gè) LCD 配置寄存器, s3c2410fb_hw 定義在 mach-s3c2410/include/mach/fb.h 中*/*定義一個(gè)數(shù)組來(lái)充當(dāng)調(diào)色板據(jù)描述,TFT 屏色位模式為
37、8BPP 時(shí),調(diào)色板(顏色表)的長(zhǎng)度為 256,調(diào)色板起始地址為 0 x4D000400*/u32palette_buffer256; u32 pseudo_pal16;unsignedpalette_ready; /*標(biāo)識(shí)調(diào)色板是否準(zhǔn)備好了*/;/*用做清空調(diào)色板(顏色表)*/#define PALETTE_BUFF_CLEAR (0 x80000000)/*LCD驅(qū)動(dòng)結(jié)構(gòu)體,驅(qū)動(dòng)結(jié)構(gòu)體定義在 platform_device.h 中,該結(jié)構(gòu)體成員接口函數(shù)在第步中實(shí)現(xiàn)*/sic struct platform_driver lcd_fb_driver =.probe= lcd_fb_probe
38、,/*FrameBuffer 設(shè)備探測(cè)*/.remove= devexit_p(lcd_fb_remove), /*FrameBuffer 設(shè)備移除*/.suspend= lcd_fb_suspend,/*FrameBuffer 設(shè)備掛起*/.resume= lcd_fb_resume,/*FrameBuffer 設(shè)備恢復(fù)*/.driver=/*注意這里的名稱一定要和系統(tǒng)中定義設(shè)備的地方一致,這樣才能把設(shè)備與該設(shè)備的驅(qū)動(dòng)關(guān)聯(lián)起來(lái)*/.name = s3c2410-lcd,.owner = THIS_MODULE,;sic init lcd_init(void)/*在 Linux 中,幀緩沖設(shè)備
39、被看做是設(shè)備,所以這里設(shè)備*/return platform_driver_register(&lcd_fb_driver);sic void exit lcd_exit(void)/*注銷設(shè)備*/ platform_driver_unregister(&lcd_fb_driver);、LCD設(shè)備各接口函數(shù)的實(shí)現(xiàn):/*LCD FrameBuffer 設(shè)備探測(cè)的實(shí)現(xiàn),注意這里使用一個(gè) devinit 宏,到 lcd_fb_remove 接口函數(shù)實(shí)現(xiàn)的地方講解*/sic devinit lcd_fb_probe(struct platform_device *pdev)i; ret;struct
40、resource *res;/*用來(lái)保存從 LCD設(shè)備中獲取的 LCD 資源*/struct fb_info*fbinfo; /*FrameBuffer 驅(qū)動(dòng)所對(duì)應(yīng)的 fb_info 結(jié)構(gòu)體*/struct s3c2410fb_mach_info *mach_info; /*保存從內(nèi)核中獲取的平臺(tái)設(shè)備數(shù)據(jù)*/struct my2440fb_var *fbvar; /*上面定義的驅(qū)動(dòng)程序全局變量結(jié)構(gòu)體*/struct s3c2410fb_display *display; /*LCD 屏的配置信息結(jié)構(gòu)體,該結(jié)構(gòu)體定義在 mach-s3c2410/include/mach/fb.h 中*/*獲取
41、LCD 硬件相關(guān)信息數(shù)據(jù),面講過(guò)內(nèi)核使用 s3c24xx_fb_set_platdata 函數(shù)將 LCD 的硬件相關(guān)信息保存到了 LCD中,所以這里就從中取出來(lái)在驅(qū)動(dòng)中使用*/module_init(lcd_init); module_exit(lcd_exit);MODULE_LICENSE(GPL); MODULE_AUTHOR(Huang Gang);MODULE_DESCRIPTION(My2440 LCD FrameBuffer Driver);mach_info = pdev-dev.platform_data; if(mach_info = NULL)/*判斷獲取數(shù)據(jù)是否成功*/
42、dev_err(&pdev-dev, no platform data for lcdn); return -EINVAL;/*獲得在內(nèi)核中定義的 FrameBuffer設(shè)備的 LCD 配置信息結(jié)構(gòu)體數(shù)據(jù)*/display = mach_info-displays + mach_info-default_display;/*給 fb_info 分配空間,大小為 my2440fb_var 結(jié)構(gòu)的內(nèi)存, framebuffer_alloc 定義在 fb.h 中在 fbsysfs.c 中實(shí)現(xiàn)*/fbinfo = framebuffer_alloc(sizeof(struct my2440fb_var
43、), &pdev-dev);if(!fbinfo)dev_err(&pdev-dev, framebuffer alloc of registers failedn);ret = -ENOMEM;goto err_noirq;platform_set_drvdata(pdev, fbinfo);/*重新將 LCD設(shè)備數(shù)據(jù)設(shè)置為 fbinfo,好在后面的一些函數(shù)中來(lái)使用*/*這里的用途其實(shí)就是將fb_info 的成員par(注意是一個(gè)void 類型的指針)指向這里的私有變量結(jié)構(gòu)體 fbvar,目的是到其他接口函數(shù)中再取出 fb_info 的成員 par,從而能繼續(xù)使用這里的私有變量*/fbvar
44、 = fbinfo-par; fbvar-dev = &pdev-dev;/*在系統(tǒng)定義的 LCD設(shè)備資源中獲取 LCD 中斷號(hào),platform_get_irq 定義在 platform_device.h 中*/fbvar-lcd_irq_no = platform_get_irq(pdev, 0); ivar-lcd_irq_no dev, no lcd irq for platformn); return -ENOENT;/*獲取 LCD設(shè)備所使用的 IO 端口資源,注意這個(gè) IORESOURCE_MEM標(biāo)志和 LCD設(shè)備定義中的一致*/res = platform_get_resour
45、ce(pdev, IORESOURCE_MEM, 0); if(res = NULL)/*判斷獲取資源是否成功*/dev_err(&pdev-dev, failed to get memory region resourcen);return -ENOENT;/*申請(qǐng) LCD IO 端口所占用的 IO 空間(注意理解 IO 空間和內(nèi)存空間的區(qū)別),request_mem_region 定義在 ioport.h 中*/fbvar-lcd_mem = request_mem_region(res-start, res-end - res-start + 1, pdev-name);ivar-lcd
46、_mem = NULL)/*判斷申請(qǐng) IO 空間是否成功*/dev_err(&pdev-dev, failed to reserve memory regionn); return -ENOENT;/*將LCD 的IO 端口占用的這段IO 空間到內(nèi)存的虛擬地址,ioremap定義在 io.h 中注意:IO 空間要后才能使用,以后對(duì)虛擬地址的操作就是對(duì) IO空間的操作*/fbvar-lcd_base = ioremap(res-start, res-end - res-start +1);ivar-lcd_base = NULL)/*判斷虛擬地址是否成功*/dev_err(&pdev-dev,
47、ioremap() of registers failedn); ret = -EINVAL;goto err_nomem;/*從鐘隊(duì)列中獲取 LCD 的時(shí)鐘,這里為什么要取得這個(gè)時(shí)鐘,從 LCD 屏的時(shí)序圖上看,各種控制信號(hào)的延遲都跟 LCD 的時(shí)鐘有關(guān)系統(tǒng)的一些時(shí)鐘定義在 arch/arm/plat-s3c24xx/s3c2410-clock.c 中*/fbvar-lcd_clock = clk_get(NULL, lcd); if(!fbvar-lcd_clock)/*判斷獲取時(shí)鐘是否成功*/dev_err(&pdev-dev, failed to find lcd clock sour
48、cen);ret = -ENOENT;goto err_nomap;/*時(shí)鐘獲取后要使能后才可以使用,clk_enable 定義在 arch/arm/plat-s3c/clock.c 中*/clk_enable(fbvar-lcd_clock);/*申請(qǐng) LCD 中斷服務(wù),上面獲取的中斷號(hào) lcd_fb_irq,使用快速中斷方式:IRQF_DISABLED中斷服務(wù)程序?yàn)?lcd_fb_irq,將 LCD設(shè)備 pdev 做參數(shù)傳遞過(guò)去了*/ret = request_irq(fbvar-lcd_irq_no, lcd_fb_irq, IRQF_DISABLED, pdev-name, fbvar
49、);if(ret)/*判斷申請(qǐng)中斷服務(wù)是否成功*/dev_err(&pdev-dev, IRQ%d error %dn, fbvar-lcd_irq_no,ret);ret = -EBUSY;goto err_noclk;/*好了,以上是對(duì)要使用的資源進(jìn)行了獲取和設(shè)置下面就開(kāi)始初始化填充 fb_info 結(jié)構(gòu)體*/*首先初始化 fb_info 中代表 LCD 固定參數(shù)的結(jié)構(gòu)體 fb_fix_screeninfo*/*像素值與顯示內(nèi)存的關(guān)系有 5 種,定義在 fb.h 中現(xiàn)在采用 FB_TYPE_PACKED_PIXELS 方式,在該方式下,像素值與內(nèi)存直接對(duì)應(yīng),比如在顯示內(nèi)存某單元寫(xiě)入一個(gè)1時(shí)
50、,該單元對(duì)應(yīng)的像素值也將是1,這使得應(yīng)用層把顯示內(nèi)存到用戶空間變得非常方便 Linux 中當(dāng)LCD 為TFT 屏?xí)r,顯示驅(qū)動(dòng)管理顯示內(nèi)存就是基于這種方式*/strcpy(fbinfo-fix.id, driver_name);/*字符串形式的標(biāo)識(shí)符*/ fbinfo-fix.type = FB_TYPE_PACKED_PIXELS;fbinfo-fix.type_aux = 0;/*以下這些根據(jù) fb_fix_screeninfo 定義中的描述,當(dāng)沒(méi)有硬件是都設(shè)為 0*/fbinfo-fix.xpanstep = 0;fbinfo-fix.ypanstep = 0;fbinfo-fix.ywr
51、apstep= 0;fbinfo-fix.accel = FB_ACCEL_NONE;/*接著,再初始化 fb_info 中代表 LCD 可變參數(shù)的結(jié)構(gòu)體 fb_var_screeninfo*/fbinfo-var.nonstd= 0;fbinfo-var.activate= FB_ACTIVATE_NOW; fbinfo-var.accel_flags= 0;fbinfo-var.vmode= FB_VMODE_NONERLACED;fbinfo-var.xres= display-xres;fbinfo-var.yres= display-yres; fbinfo-var.bits_per
52、_pixel= display-bpp;/*指定對(duì)底層硬件操作的函數(shù)指針, 因內(nèi)容較多故其定義在第步中再講*/fbinfo-fbops= &my2440fb_ops;fbinfo-flags= FBINFO_FLAG_DEFAULT; fbinfo-pseudo_palette= &fbvar-pseudo_pal;/*初始化色調(diào)色板(顏色表)為空*/ for(i = 0; i palette_bufferi = PALETTE_BUFF_CLEAR;for (i = 0; i num_displays; i+) /*fb 緩存的長(zhǎng)度*/*計(jì)算 FrameBuffer 緩存的最大大小,這里右移
53、 3 位(即除以 8)是因?yàn)樯荒J?BPP 是以位為*/unsigned long smem_len = (mach_info-displaysi.xres * mach_info-displaysi.yres * mach_info-displaysi.bpp) 3;iinfo-fix.smem_len fix.smem_len = smem_len;/*初始化 LCD 控制器之前要延遲一段時(shí)間*/ msleep(1);/*初始化完 fb_info 后,開(kāi)始對(duì) LCD 各寄存器進(jìn)行初始化,其定義在后面講到*/my2440fb_init_registers(fbinfo);/*初始化完寄存器
54、后,開(kāi)始檢查 fb_info 中的可變參數(shù),其定義在后面講到*/my2440fb_check_var(fbinfo);/*申請(qǐng)幀緩沖設(shè)備 fb_info 的顯示緩沖區(qū)空間,其定義在后面講到*/ ret = my2440fb_map_memory(fbinfo);if (ret)dev_err(&pdev-dev, failed to allocateRAM: %dn,ret);ret = -ENOMEM;goto err_nofb;/*最后,這個(gè)幀緩沖設(shè)備 fb_info 到系統(tǒng)中, register_framebuffer 定義在 fb.h 中在 fbmem.c 中實(shí)現(xiàn)*/ret = reg
55、ister_framebuffer(fbinfo); if (ret dev, failed to register framebuffer device:%dn, ret);goto err_nomem;/*對(duì)設(shè)備文件系統(tǒng)的支持(對(duì)設(shè)備文件系統(tǒng)的理解請(qǐng)參閱: Linux 之我行設(shè)備文件系統(tǒng)剖析與使用)創(chuàng)建 frambuffer 設(shè)備文件,device_create_file 定義在 linux/device.h 中*/ret = device_create_file(&pdev-dev, &dev_attr_debug); if (ret)dev_err(&pdev-dev, failed
56、to add debug attributen);return 0;/*以下是上面錯(cuò)誤處理的跳轉(zhuǎn)點(diǎn)*/ err_nomem:release_resource(fbvar-lcd_mem); kfree(fbvar-lcd_mem);err_nomap:iounmap(fbvar-lcd_base);err_noclk:clk_disable(fbvar-lcd_clock); clk_put(fbvar-lcd_clock);err_noirq:free_irq(fbvar-lcd_irq_no, fbvar);err_nofb:platform_set_drvdata(pdev, NULL)
57、; framebuffer_release(fbinfo);err_nomem:my2440fb_unmap_memory(fbinfo);return ret;/*LCD 中斷服務(wù)程序*/sic irqreturn_t lcd_fb_irq(irq, void *dev_id)struct my2440fb_var*fbvar = dev_id; void iomem *lcd_irq_base;unsigned long lcdirq;/*LCD 中斷掛起寄存器址*/lcd_irq_base = fbvar-lcd_base + S3C2410_LCDBASE;/*LCD 中斷掛起寄存器的
58、值*/lcdirq = readl(lcd_irq_base + S3C24XX_LCDPND);/*判斷是否為中斷掛起狀態(tài)*/ if(lcdirq & S3C2410_LCD_FRSYNC)/*填充調(diào)色板*/if (fbvar-palette_ready)my2440fb_write_palette(fbvar);/*設(shè)置幀已中斷請(qǐng)求*/wri(S3C2410_LCD_FRSYNC, lcd_irq_base + S3C24XX_LCDPND);wri(S3C2410_LCD_FRSYNC, lcd_irq_base + S3C24XX_LCDSRCPND);return IRQ_HANDL
59、ED;/*填充調(diào)色板*/sic void my2440fb_write_palette(struct my2440fb_var *fbvar)unsignedi;void iomem *regs = fbvar-lcd_base;fbvar-palette_ready = 0;for (i = 0; i palette_bufferi;if (ent = PALETTE_BUFF_CLEAR)continue;wri(ent, regs + S3C2410_TFTPAL(i);if (readw(regs + S3C2410_TFTPAL(i) = ent)fbvar-palette_buff
60、eri = PALETTE_BUFF_CLEAR;elsefbvar-palette_ready = 1;/*LCD 各寄存器進(jìn)行初始化*/sicmy2440fb_init_registers(struct fb_info *fbinfo)unsigned long flags; void iomem *tpal; void iomem *lpcsel;/*從lcd_fb_probe 探測(cè)函數(shù)設(shè)置的私有變量結(jié)構(gòu)體中再獲得LCD 相關(guān)信息的數(shù)據(jù)*/struct my2440fb_var*fbvar = fbinfo-par; struct s3c2410fb_mach_info *mach_in
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 語(yǔ)文素養(yǎng)大賽策劃書(shū)3篇
- 2025年榆林能源科技職業(yè)學(xué)院高職單招語(yǔ)文2018-2024歷年參考題庫(kù)頻考點(diǎn)含答案解析
- 專題02 漫畫(huà)素材類選擇題(50題)
- 2024年電商應(yīng)用與品牌市場(chǎng)洞察報(bào)告
- 課題申報(bào)參考:數(shù)據(jù)驅(qū)動(dòng)的帆板高效推進(jìn)搖帆策略研究
- 駕馭考試戰(zhàn)場(chǎng)的戰(zhàn)術(shù)思維
- 幼兒植樹(shù)節(jié)出游活動(dòng)策劃方案五篇
- 酒店委托經(jīng)營(yíng)合同范本
- 范文二手房買賣合同
- 商服用房買賣合同
- 文檔協(xié)同編輯-深度研究
- 七年級(jí)數(shù)學(xué)新北師大版(2024)下冊(cè)第一章《整式的乘除》單元檢測(cè)習(xí)題(含簡(jiǎn)單答案)
- 2024-2025學(xué)年云南省昆明市盤龍區(qū)高一(上)期末數(shù)學(xué)試卷(含答案)
- 五年級(jí)上冊(cè)寒假作業(yè)答案(人教版)
- 2024年財(cái)政部會(huì)計(jì)法律法規(guī)答題活動(dòng)題目及答案一
- 2025年中考語(yǔ)文復(fù)習(xí)熱搜題速遞之說(shuō)明文閱讀(2024年7月)
- 和達(dá)投資集團(tuán)(杭州)有限公司招聘筆試沖刺題2025
- 綜治工作培訓(xùn)課件
- 2024年云網(wǎng)安全應(yīng)知應(yīng)會(huì)考試題庫(kù)
- 2024年全國(guó)職業(yè)院校技能大賽高職組(智能節(jié)水系統(tǒng)設(shè)計(jì)與安裝賽項(xiàng))考試題庫(kù)-下(多選、判斷題)
- 2024年廣東省事業(yè)單位考試真題及答案5
評(píng)論
0/150
提交評(píng)論