u-boot-2009.08在mini2440上的移植(七)---增加LCD顯示功能
移植環(huán)境
1,主機(jī)環(huán)境:VMare下CentOS 5.5 ,1G內(nèi)存。
2,集成開發(fā)環(huán)境:Elipse IDE
3,編譯編譯環(huán)境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。
4,開發(fā)板:mini2440,2M nor flash,128M nand flash。
5,u-boot版本:u-boot-2009.08
6,參考文章:
http://blogold.chinaunix.net/u3/101649/showart.php?id=2105215
http://blog.chinaunix.net/space.php?uid=23787856&do=blog&id=115382
http://blogimg.chinaunix.net/blog/upfile2/100811115954.pdf
7.1添加 LCD 顯示功能
對于這個 LCD 的支持是參考Openmoko 的代碼移植的。Openmoko 的GTA2 使用的是S3C2442 的CPU,在LCD 控制器上是一樣的。而GTA2 在U-boot 的可以在LCD 上顯示字符,而且對于軟件分層的U-boot 來說,只要將底層驅(qū)動移植過來并調(diào)整好初始化參數(shù)就可以在LCD 上顯示console。下圖是LCD驅(qū)動軟件分層執(zhí)行流程示意??梢钥吹絃CD在執(zhí)行時最終調(diào)用的是底層的board_video_init()函數(shù),其主要作用是對LCD控制寄存器進(jìn)行初始化??捎捎脩舾鶕?jù)實(shí)際LCD硬件編寫。
由于友善之臂使用了兩種屏,他們在一個參數(shù)上有很小的差別,而屏有不可以通過程序去識別,所以只能簡單的通過Nand Flash配置來區(qū)分導(dǎo)入的參數(shù)(64MB Nand 的板子使用的都是NEC 的,其他的都是統(tǒng)寶的)。這個功能的移植修改了5 個文件(包括drivers/video/Makefile,以及前面已經(jīng)修改過的board/samsung/mini2440/mini2440.c 文件)。
【1】在/drivers/video/下添加一個驅(qū)動文件名為s3c2410_fb.c,將下面內(nèi)容粘貼進(jìn)去:
/*
* (C) Copyright 2006 by OpenMoko, Inc.
* Author: Harald Welte
*
* 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
#if defined(CONFIG_VIDEO_S3C2410)
#include
#include "videomodes.h"
#include
/*
* 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 ("%sn", 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 = 240;
pGD->winSizeY = pGD->plnSizeY = 320;
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 */