一、LCD时序配置
fl2440开发板的LCD是3.5寸屏型号是WXCAT35-TG3#001,这是一款320x240分辨率的TFT LCD屏,先来了解一下TFT LCD的时序如下:
图1 TFT LCD时序
(1)VSYNC信号来一个脉冲时,表示一帧的开始
(2) VSPW表示VSYNC信号的脉冲宽度为(VSPW+1)个HSYNC信号周期,即(VSPW+1)行,这(VSPW+1)行的数据无效。
(3)VSYNC信号脉冲之后,还要经过(VBPD+1)个(HSYNC)信号周期,有效的行数据才出现。所以,在VSYNC信号有效之后,总共还要经过(VSPW+1+VBPD+1)个无效行,
(4)随后连续发出(LINEVAL+1)行的有效数据
(5)最后是(VFPD+1)个无效行,完整的一帧结束,紧接着就是下一帧的数据了(即下一个VSYNC信号)。
(6)HSYNC信号有效时,表示一行数据的开始
(7) HSPW表示HSYNC信号的脉冲宽度为(HSPW+1)个VCLK信号周期,即(HSPW+1)个像素,这(HSPW+1)个像素的数据无效。
(8)HSYNC信号脉冲之后,还要经过(HBPD+1)个VCLK信号周期,有效的像素数据才会出现。所以,在HSYNC信号有效之后,总共还要经过(HSPW + 1 + HBPD + 1)个无效的像素,第一个有效像素才出现。
(9)随后即连续发出(HOZVAL+1)个像素的有效数据。
(10)最后是(HFPD+1)个无效的像素,完整的一行结束,紧接着就是下一行的数据了(即下一个HSYNC信号)。
TFT LCD的正常工作主要需要配置S3C2440的寄存器LCDCON1~LCDCON5。
二、u-boot支持LCD的配置工作
首先要添加一个文件,driver/video/s3c2410_fb.c,其内容为:/* * (C) Copyright 2006 by OpenMoko, Inc. * Author: Harald Welte <[email protected]> * * 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)||defined(CONFIG_VIDEO_S3C2440) #include <video_fb.h> #include <asm/arch/s3c2410.h> #include "videomodes.h" /* * Export Graphic Device */ static GraphicDevice smi; #define VIDEO_MEM_SIZE 0x200000 /* 240x320x16bit = 0x25800 bytes */ extern void board_video_init( GraphicDevice *pGD); /* * Add by yanghao */ /******************************************************************************* * * Init video chip with common Linux graphic modes (lilo) */ void *video_hw_init (void) { struct s3c24x0_lcd * const lcd = s3c24x0_get_base_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 = CONFIG_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 ", CONFIG_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); } #endif /* CONFIG_VIDEO_S3C2410 */
修改driver/video/videomodes.h文件第25行左右为:
#ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE //#define CONFIG_SYS_DEFAULT_VIDEO_MODE 0x301 #define CONFIG_SYS_DEFAULT_VIDEO_MODE 0x211 #endif
紧接着修改driver/video/videomodes.h第81行左右为:
#define RES_MODE_1280x1024 5 #define RES_MODE_240x320 6 #define RES_MODES_COUNT 7 #define VESA_MODES_COUNT 20
在driver/video/videomodes..c文件struct ctfb_vesa_modes vesa_modes定义中添加(第78行左右)本开发板LCD的相关配置:
{0x211, RES_MODE_240x320, 16},
在driver/video/videomodes..c文件struct ctfb_res_modes res_mode_init定义中添加(第100行左右)本开发板LCD的相关配置:
{320, 240, 158025, 58, 15, 3, 5, 8, 15, 0, FB_VMODE_NONINTERLACED},
紧接着修改driver/video/Makefile文件,在41行后添加:
COBJS-$(CONFIG_VIDEO_S3C2440) += videomodes.o COBJS-$(CONFIG_VIDEO_S3C2440) += s3c2410_fb.o
最后,修改文件board/fl2440/fl2440.c,在文件最后添加:
/* * Add by yanghao */ #if defined(CONFIG_VIDEO_S3C2440) #define MVAL (13) #define MVAL_USED (0) #define INVVDEN (1) #define BSWP (0) #define HWSWP (1) //TFT 240320 #define LCD_XSIZE_TFT_240320 (320) #define LCD_YSIZE_TFT_240320 (240) //TFT 240320 #define HOZVAL_TFT_240320 (LCD_XSIZE_TFT_240320-1) #define LINEVAL_TFT_240320 (LCD_YSIZE_TFT_240320-1) //Timing parameter for WXCAT35-TG#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) { struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd(); /*Configuration for fl2440*/ lcd->LCDCON1 = (CLKVAL_TFT_240320 <<8)|(MVAL_USED <<7)|(3<<5)|(12<<1)|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 = (1<<11)|(1<<9)|(1<<8)|(1<<3)|(BSWP<<1)|(HWSWP); lcd->LPCSEL = 0x00000000; } #endif /*CONFIG_VIDEO_S3C2440*/
最后还需要在开发板配置文件中添加LCD屏支持的宏定义,修改文件include/configs/fl2440.h文件,在文件中添加:
#include <video_fb.h> //头文件定义处添加
/*****************add by yanghao support LCD文件末尾处添加********************/ /*LCD support*/ #define CONFIG_VIDEO_S3C2440 1 #define CONFIG_VIDEO_LOGO 1 #define CONFIG_VIDEO_BMP_LOGO 1 #define VIDEO_FB_16BPP_WORD_SWAP 1 #define CONFIG_CMD_BMP 1 //#define CONFIG_LCD 1 #define CONFIG_VIDEO 1 #define CONFIG_CFB_CONSOLE 1 #define CFG_CONSOLE_INFO_QUIET //support display of console information at boot #define LCD_VIDEO_ADDR 0x33b00000 /*for PC-keyboard*/ #define VIDEO_KBD_INIT_FCT 0 /*for PC-keyboard*/ #define VIDEO_TSTC_FCT serial_tstc #define VIDEO_GETC_FCT serial_getc #define CONFIG_SERIAL_MULTI 1 /*LCD support*/
重新上电后,uboot的输出就都显示在LCD上了,我们的输入还是选择的串口输入,输入信息也都显示在LCD屏之上效果图如下: