由于linux啟動(dòng)代碼,仍然出現(xiàn)亂碼,而我將啟動(dòng)信息輸出到lcd就沒(méi)有亂碼。暫時(shí)這個(gè)問(wèn)題還沒(méi)有解決,lcd其實(shí)早已完成,今天整理下,再解決那個(gè)問(wèn)題。 下面是我繪制的主要的lcd驅(qū)動(dòng)調(diào)用流程圖。start_armboot()在lib_arm/board.c中,stdio_init()在common/stdio.cdrv_video_init(),video_init(),video_logo (),video_fb_address()在drivers/video/cfb_console.c中,video_hw_init()在drivers/video/s3c2410_fb.c中,board_video_init()在board/samsung/TE2440II/TE2440II.c。 最終調(diào)用了board_video_init()函數(shù),這個(gè)函數(shù)由我們自己來(lái)編寫,由于以前寫過(guò)裸機(jī)的lcd程序,所以時(shí)序就可以直接拿來(lái)用,不用調(diào)了,哈哈。在這個(gè)函數(shù)中主要還是對(duì)那5個(gè)lcd的控制寄存器進(jìn)行初始化。這里要注意根據(jù)不同的屏,進(jìn)行x,y的調(diào)整,我用的是東華WXCAT35-TG3#001,主要就是初始化一個(gè)GraphicDevice *pGD結(jié)構(gòu)體。 #define MVAL (0) #define MVAL_USED (0) //0=each frame 1=rate by MVAL #define INVVDEN (0) //0=normal 1=inverted #define BSWP (0) //Byte swap control #define HWSWP (0) //Half word swap control //TFT 240320 #define LCD_XSIZE_TFT_240320 (320) #define LCD_YSIZE_TFT_240320 (240) //TFT240320 #define HOZVAL_TFT_240320 (LCD_XSIZE_TFT_240320-1) #define LINEVAL_TFT_240320 (LCD_YSIZE_TFT_240320-1) //Timing parameter for WXCAT35-TG3#001" #define VBPD_240320 (3) #define VFPD_240320 (5) #define VSPW_240320 (15) #define HBPD_240320 (58) #define HFPD_240320 (15) #define HSPW_240320_WXCAT35 (8) //Adjust the horizontal displacement of the screen #define CLKVAL_TFT_240320 (7) //FCLK=405MHz,HCLK=101.25MHz,VCLK=4602272Hz void board_video_init(GraphicDevice *pGD) { S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD(); S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); /* FIXME: select LCM type by env variable */ /* Configuration for GTA01 LCM on QT2410 */ lcd->LCDCON1 = 0x00000778; /* CLKVAL=7, BPPMODE=16bpp, TFT, ENVID=0 */ lcd->LCDCON2 = (VBPD_240320<<24)|(LINEVAL_TFT_240320<<14)|(VFPD_240320<<6)|(VSPW_240320); lcd->LCDCON3 = (HBPD_240320<<19)|(HOZVAL_TFT_240320<<8)|(HFPD_240320); lcd->LCDCON4 = (MVAL<<8)|(HSPW_240320_WXCAT35); lcd->LCDCON5 = 0x00000f09; lcd->LPCSEL = 0x00000000; } 明白上邊的流程后一切變得很簡(jiǎn)單,只要根據(jù)自己的屏調(diào)整好時(shí)序就行了。添加一個(gè)驅(qū)動(dòng)文件這個(gè)是一個(gè)外國(guó)的牛人已經(jīng)寫好的。在drivers/video/下添加s3c2410_fb.c。代碼如下: /* * (C) Copyright 2006 by OpenMoko, Inc. * Author: Harald Welte <laforge@openmoko.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include <common.h> #if defined(CONFIG_VIDEO_S3C2410) #include <video_fb.h> #include "videomodes.h" #include <s3c2410.h> /* * Export Graphic Device */ GraphicDevice smi; #define VIDEO_MEM_SIZE 0x200000 /* 240x320x16bit = 0x25800 bytes */ extern void board_video_init(GraphicDevice *pGD); /******************************************************************************* * * Init video chip with common Linux graphic modes (lilo) */ void *video_hw_init (void) { S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD(); GraphicDevice *pGD = (GraphicDevice *)&smi; int videomode; unsigned long t1, hsynch, vsynch; char *penv; int tmp, i, bits_per_pixel; struct ctfb_res_modes *res_mode; struct ctfb_res_modes var_mode; // unsigned char videoout; /* Search for video chip */ printf("Video: "); tmp = 0; videomode = CFG_SYS_DEFAULT_VIDEO_MODE; /* get video mode via environment */ if ((penv = getenv ("videomode")) != NULL) { /* deceide if it is a string */ if (penv[0] <= '9') { videomode = (int) simple_strtoul (penv, NULL, 16); tmp = 1; } } else { tmp = 1; } if (tmp) { /* parameter are vesa modes */ /* search params */ for (i = 0; i < VESA_MODES_COUNT; i++) { if (vesa_modes[ i].vesanr == videomode) break; } if (i == VESA_MODES_COUNT) { printf ("no VESA Mode found, switching to mode 0x%x ", CFG_SYS_DEFAULT_VIDEO_MODE); i = 0; } res_mode = (struct ctfb_res_modes *) &res_mode_init[vesa_modes[ i]. resindex]; bits_per_pixel = vesa_modes[ i].bits_per_pixel; } else { res_mode = (struct ctfb_res_modes *) &var_mode; bits_per_pixel = video_get_params (res_mode, penv); } /* calculate hsynch and vsynch freq (info only) */ t1 = (res_mode->left_margin + res_mode->xres + res_mode->right_margin + res_mode->hsync_len) / 8; t1 *= 8; t1 *= res_mode->pixclock; t1 /= 1000; hsynch = 1000000000L / t1; t1 *= (res_mode->upper_margin + res_mode->yres + res_mode->lower_margin + res_mode->vsync_len); t1 /= 1000; vsynch = 1000000000L / t1; /* fill in Graphic device struct */ sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres, res_mode->yres, bits_per_pixel, (hsynch / 1000), (vsynch / 1000)); printf ("%s\n", pGD->modeIdent); pGD->winSizeX = res_mode->xres; pGD->winSizeY = res_mode->yres; pGD->plnSizeX = res_mode->xres; pGD->plnSizeY = res_mode->yres; switch (bits_per_pixel) { case 8: pGD->gdfBytesPP = 1; pGD->gdfIndex = GDF__8BIT_INDEX; break; case 15: pGD->gdfBytesPP = 2; pGD->gdfIndex = GDF_15BIT_555RGB; break; case 16: pGD->gdfBytesPP = 2; pGD->gdfIndex = GDF_16BIT_565RGB; break; case 24: pGD->gdfBytesPP = 3; pGD->gdfIndex = GDF_24BIT_888RGB; break; } /* statically configure settings */ pGD->winSizeX = pGD->plnSizeX = 320; pGD->winSizeY = pGD->plnSizeY = 240; pGD->gdfBytesPP = 2; pGD->gdfIndex = GDF_16BIT_565RGB; pGD->frameAdrs = LCD_VIDEO_ADDR; pGD->memSize = VIDEO_MEM_SIZE; board_video_init(pGD); lcd->LCDSADDR1 = pGD->frameAdrs >> 1; /* This marks the end of the frame buffer. */ lcd->LCDSADDR2 = (lcd->LCDSADDR1&0x1fffff) + (pGD->winSizeX+0) * pGD->winSizeY; lcd->LCDSADDR3 = (pGD->winSizeX & 0x7ff); /* Clear video memory */ memset((void *)pGD->frameAdrs, 0, pGD->memSize); /* Enable Display */ lcd->LCDCON1 |= 0x01; /* ENVID = 1 */ return ((void*)&smi); } void video_set_lut (unsigned int index, /* color number */ unsigned char r, /* red */ unsigned char g, /* green */ unsigned char b /* blue */ ) { } #endif /* CONFIG_VIDEO_S3C2410 */ 在你的配置頭文件中添加如下宏定義: #define CONFIG_CMD_BMP #define CONFIG_VIDEO #define CONFIG_VIDEO_S3C2410 #define CONFIG_VIDEO_LOGO #define VIDEO_FB_16BPP_PIXEL_SWAP #define CONFIG_VIDEO_SW_CURSOR #define CONFIG_VIDEO_BMP_LOGO 這樣就基本完成了,重新啟動(dòng)一下是不是就顯示出samsung的logo了。如果先改成自己喜歡的圖片,修改tools/logos/denx.bmp,記住一定是是8bpp的bmp圖,修改Makefile文件,修改/tools目錄下的Makefile文件,大約是44"46行, ifeq ($(LOGO_BMP),) LOGO_BMP= logos/denx.bmp endif 把 denx.bmp 替換為你需要顯示的logo圖片的文件名,保存退出,重新編譯uboot。圖片的轉(zhuǎn)化方法,在終端輸入命令: jpegtopnm $1 | ppmquant 31 | ppmtobmp -bpp 8 > $2 使用方法: (腳本名) ( 待處理的JPG圖片名) (輸出文件名) 這樣就可以顯示出你自己喜歡的logo圖片了。 如果想將串口的打印信息顯示在lcd上,添加環(huán)境變量。 #define CONFIG_EXTRA_ENV_SETTINGS \ "stdin=serial\0" \ "stdout=vga" \ "stderr=serial\0" \ 只要讓stdout等于vga就可以了。在lib_arm/board.c文件中可以看到console_init初始化兩次,我們修改的影響第二次的初始化,第一次的不影響,所以還會(huì)有部分輸出信息顯示在串口上的。Lcd就到這里,有什么問(wèn)題我再及時(shí)改正吧。 李萬(wàn)鵬 |