您的位置:首页 > 其它

smdkv210 uboot增加LCD显示(二)

2012-05-03 23:05 330 查看
如果只是简单的显示图片或字符,smdkv210 uboot增加LCD显示(一)中的方法就可以了,但是要使用console的话

就有另一种方法,主要参考u-boot-2010.09
for mini6410 (add LCD support )

http://blog.chinaunix.net/uid-20543672-id-94391.html

还有u-boot-2009.08在mini2440上的移植(七)---增加LCD显示功能

http://blog.163.com/liuqiang_mail@126/blog/static/10996887520117622235857/

其实要在U-boot中添加LCD支持其实很简单,只要你的CPU支持类似framebuffer的机制,就只要添加一个初始化LCD 控制器和一个GraphicDevice *pGD结构体的代码就基本可以了。

下图是LCD驱动软件分层执行流程示意。可以看到LCD在执行时最终调用的是底层的board_video_init()函数,其主要作用是对LCD控制寄存器进行初始化。可由用户根据实际LCD硬件编写。



(1)在/drivers/video/下添加一个驱动文件名为s5pc110_fb.c,将下面内容粘贴进去:

#include <common.h>

#if defined(CONFIG_VIDEO_S5PC110)

#include <video_fb.h>

#include "videomodes.h"

#include <regs-fb.h>

#include <s5pc110.h>

/*

* Export Graphic Device

*/

GraphicDevice smi;

#define VIDEO_MEM_SIZE 0x200000 /*NEC 4.3 inches: 480x272x16bit = 0x3FC00 bytes 7 inches:800*480*4bytes = 0x177000 bytes*/

//CPU: S5pc110@1000MHz

// Fclk = 1000MHz, Hclk = 200MHz, Pclk = 100MHz (ASYNC Mode)

extern void board_video_init(GraphicDevice *pGD);

/*******************************************************************************

*

* Init video chip with common Linux graphic modes (lilo)

*/

void *video_hw_init (void)

{

// s3c64xx_fb * const fb = s3c64xx_get_base_fb();

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;

int clkval;

// 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;

case 32:

pGD->gdfBytesPP = 4;

pGD->gdfIndex = GDF_32BIT_X888RGB;

break;

}

#if 0

/* statically configure settings for debug*/

pGD->winSizeX = pGD->plnSizeX = 480;

pGD->winSizeY = pGD->plnSizeY = 272;

pGD->gdfBytesPP = 2;

pGD->gdfIndex = GDF_16BIT_565RGB;

#endif

pGD->frameAdrs = LCD_VIDEO_ADDR; //in config file :include/configs/mini6410.h

pGD->memSize = VIDEO_MEM_SIZE;

/* Clear video memory */

memset((void *)pGD->frameAdrs, 0x00, pGD->memSize);

board_video_init(pGD); //in board init file :board/samsung/mini6410/mini6410.c for gpio etc.

t1 = res_mode->pixclock;

t1 /= 1000;

t1 = 1000000000L / t1;

clkval = (CONFIG_SYS_VIDEO_VCLOCK_HZ / t1) - 1;

// clkval = 1; //for debug

VIDCON0 = ( VIDCON0_VIDOUT_RGB
| VIDCON0_PNRMODE_RGB_P |

VIDCON0_CLKVALUP_ALWAYS | VIDCON0_CLKVAL_F(clkval)|

VIDCON0_CLKDIR_DIVIDED| VIDCON0_CLKSEL_HCLK );

VIDCON1 = ( VIDCON1_IVSYNC_INVERT | VIDCON1_IHSYNC_INVERT);

VIDTCON0 = ( VIDTCON0_VBPD(res_mode->upper_margin) |

VIDTCON0_VFPD(res_mode->lower_margin) |

VIDTCON0_VSPW(res_mode->vsync_len));

VIDTCON1 = ( VIDTCON1_HBPD(res_mode->left_margin) |

VIDTCON1_HFPD(res_mode->right_margin) |

VIDTCON1_HSPW(res_mode->hsync_len));

VIDTCON2 = (VIDTCON2_LINEVAL(pGD->winSizeY - 1) | VIDTCON2_HOZVAL(pGD->winSizeX - 1));

#if defined(LCD_VIDEO_BACKGROUND)

WINCON0 = (WINCON_BPPMODE_16BPP_565 | WINCON_ENWIN_ENABLE | WINCON_HAWSWP_ENABLE);

VIDOSD0A = (VIDOSD_LEFT_X(0) | VIDOSD_TOP_Y(0));

VIDOSD0B = (VIDOSD_RIGHT_X(pGD->winSizeX - 1) | VIDOSD_BOTTOM_Y(pGD->winSizeY - 1));

VIDOSD0C = VIDOSD_SIZE(pGD->winSizeY * pGD->winSizeX);

#endif

WINCON1 = (WINCON_BPPMODE_16BPP_565 | WINCON_ENWIN_ENABLE | WINCON_HAWSWP_ENABLE);

VIDOSD1A = (VIDOSD_LEFT_X(0) | VIDOSD_TOP_Y(0));

VIDOSD1B = (VIDOSD_RIGHT_X(pGD->winSizeX - 1) | VIDOSD_BOTTOM_Y(pGD->winSizeY - 1));

#if defined(LCD_VIDEO_BACKGROUND)

VIDOSD1C = (VIDOSD_ALPHA0_R(LCD_VIDEO_BACKGROUND_ALPHA) |

VIDOSD_ALPHA0_G(LCD_VIDEO_BACKGROUND_ALPHA) |

VIDOSD_ALPHA0_B(LCD_VIDEO_BACKGROUND_ALPHA) );

#endif

VIDOSD1D = VIDOSD_SIZE(pGD->winSizeY * pGD->winSizeX);

WINSHMAP = WINSHMAP_CH_ENABLE(1); //Enables Channel 1

#if defined(LCD_VIDEO_BACKGROUND)

/* config Display framebuffer addr for background*/

VIDW00ADD0B0 = LCD_VIDEO_BACKGROUND_ADDR;

/* This marks the end of the frame buffer. */

VIDW00ADD1B0 = (VIDW00ADD0B0 &0xffffffff) + (pGD->winSizeX+0) * pGD->winSizeY * (pGD->gdfBytesPP);

VIDW00ADD2= ((pGD->winSizeX * pGD->gdfBytesPP) & 0x1fff);

#endif

/* config Display framebuffer addr for console*/

VIDW01ADD0B0 = pGD->frameAdrs;

/* This marks the end of the frame buffer. */

VIDW01ADD1B0 = (VIDW01ADD0B0 &0xffffffff) + (pGD->winSizeX+0) * pGD->winSizeY * (pGD->gdfBytesPP);

VIDW01ADD2= ((pGD->winSizeX * pGD->gdfBytesPP) & 0x1fff);

/* Enable Display */

VIDCON0 |= (VIDCON0_ENVID_ENABLE | VIDCON0_ENVID_F_ENABLE); /* ENVID = 1 ENVID_F = 1*/

TRIGCON = (TRGMODE_I80 | SWTRGCMD_I80); //TRIGCON = 3

/* clear background

u16 p,q;

u32* pBuffer = (u32*)pGD->frameAdrs;

for (p=0; p < pGD->winSizeX; p++)

{

for (q=0; q < pGD->winSizeY; q++)

{

*pBuffer++ = 0x555555;

}

} */

printf("Video: video_hw_init complete \n");

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_S5PC110 */

(2)打开/drivers/video/Makefile,定位到

COBJS-y += videomodes.o

COBJS-y +=s5pc110_fb.o

COBJS := $(COBJS-y)
(3)修改/drivers/video/cfb_console.c,我直接使用了tekkaman
ninja的源码

(4)打开/drivers/video/videomodes.c,修改如下:

{0x31A, RES_MODE_1280x1024, 16},

{0x31B, RES_MODE_1280x1024, 24},

{0x211, RES_MODE_240x320, 16},

{0x212, RES_MODE_800x480, 16},

};

const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {

/* x y pixclk le ri up lo hs vs s vmode */

{640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED},

{800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},

{1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED},

{960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED},

{1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED},

{1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED},

{240, 320, 90000, 1, 4, 1, 1, 30, 4, 0, FB_VMODE_NONINTERLACED},

{800, 480, 15151, 16, 48, 6, 4, 32, 0, 0, FB_VMODE_NONINTERLACED},

};

(5)打开/drivers/video/videomodes.h,修改如下:

//#ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE

//#define CONFIG_SYS_DEFAULT_VIDEO_MODE 0x301

#ifndef CFG_SYS_DEFAULT_VIDEO_MODE

#define CFG_SYS_DEFAULT_VIDEO_MODE 0x212

#endif

#define RES_MODE_1280x1024 5

#define RES_MODE_240x320 6

#define RES_MODE_800x480 7

#define RES_MODES_COUNT 8

//#define VESA_MODES_COUNT 19

#define VESA_MODES_COUNT 21

extern const struct ctfb_vesa_modes vesa_modes[];
(6)打开board/samsung/smdkc110/smdkc110.c,修改如下

int board_init(void)

{

DECLARE_GLOBAL_DATA_PTR;

// S5PC11X_GPIO * const gpio = S5PC11X_GetBase_GPIO();

//init gpio func for LCD

writel(0x10000000, GPBCON); //GPBCON [31:28]:output [27:0]:input

writel(0x1555,GPBPUD);//GPBPUD GPBPUD[7]:Pull-up/ down disabled GPBPUD[6:0]:Pull-down enabled

writel(0xc000,GPBDRV_SR);//GPBDRV GPBDRV[7]:4x GPBDRV[6:0]:1x

writel(0x10010000,GPBCON);//GPBCON [31:28],[19:16]:output [27:20],[15:0]:input

writel(0x1455,GPBPUD);//GPBPUD GPBPUD[7],[4]:Pull-up/ down disabled ,GPBPUD[6:5][3:0]:Pull-down enabled

writel(0xc300,GPBDRV_SR);//GPBDRV GPBDRV[7],[4]:4x GPBDRV[6:5][3:0]:1x

writel(0x10110000,GPBCON);//GPBCON [31:28],[23:20],[19:16]:output [27:24],[15:0]:input

writel(0x1055,GPBPUD);//GPBPUD GPBPUD[7],[5][4]:Pull-up/ down disabled ,GPBPUD[6][3:0]:Pull-down enabled

writel(0xcf00,GPBDRV_SR);//GPBDRV GPBDRV[7],[5],[4]:4x GPBDRV[6][3:0]:1x

writel(0x1,GPD1CON);//GPD1CON [23:4]:input [3:0]:output

writel(0x54,GPD1PUD);//GPD1PUD GPD1PUD[5:4],[0]:Pull-up/ down disabled ,GPBPUD[3:1]:Pull-down enabled

writel(0x3,GPD1DRV);//GPD1DRV GPD1DRV[0]:4x GPBDRV[5:1]:1x

writel(0x11,GPD1CON);//GPD1CON [23:8]:input [7:0]:output

writel(0x50,GPD1PUD);//GPD1PUD GPD1PUD[5:4],[1:0]:Pull-up/ down disabled ,GPBPUD[3:2]:Pull-down enabled

writel(0xf,GPD1DRV);//GPD1DRV GPD1DRV[1:0]:4x GPBDRV[5:2]:1x

writel(0x1001,GPD0CON);//GPD0CON GPD0CON[3],[0]:output GPD0CON[2:1]:input

writel(0x15,GPD0PUD);//GPD0PUD GPD0PUD[3]:Pull-up/ down disabled,GPD0PUD[2:0]:Pull-down enabled

writel(0xc0,GPD0DRV);//GPD0DRV GPD0DRV[3]:4x,GPD0DRV[2:0]:1x

writel(0x1000010,GPH0CON);// GPH0CON GPH0CON[6],[1]:output,GPH0CON[7],[5:2],[0]:input

writel(0x4455,GPH0PUD);// GPH0PUD GPH0PUD[6],[4]:Pull-up/ down disabled GPH0PUD[7],[5],[4:0]:Pull-down enabled

writel(0x3000,GPH0DRV);// GPH0DRV GPH0DRV[6]:4x GPH0DRV[7],[5:0]:1x

writel(0x11110000,GPBCON);//GPBCON [31:16]:output [15:0]:input

writel(0x55,GPBPUD);//GPBPUD GPBPUD[7:4]:Pull-up/ down disabled GPBPUD[3:0]:Pull-down enabled

writel(0xff00,GPBDRV_SR);//GPBDRV GPBDRV[7:4]:4x GPBDRV[3:0]:1x

writel(0x11110100,GPBCON);//GPBCON [31:16],[11:8]:output [15:12],[7:0]:input

writel(0x55,GPBPUD);//GPBPUD GPBPUD[7:4]:Pull-up/ down disabled GPBPUD[3:0]:Pull-down enabled

writel(0xff00,GPBDRV_SR);//GPBDRV GPBDRV[7:4]:4x GPBDRV[3:0]:1x

writel(0x80,GPBDAT);//GPBDAT GPBDAT[7]=1,GPBDAT[6:0]=0

writel(0x98,GPBDAT);//GPBDAT GPBDAT[7],[4:3]=1,GPBDAT[6:5],[2:0]=0

writel(0xb9,GPBDAT);//GPBDAT GPBDAT[7],[5:3],[0]=1,GPBDAT[6],[2:1]=0

writel(0xbb,GPBDAT);//GPBDAT GPBDAT[7],[5:3],[1:0]=1,GPBDAT[6],[2]=0

writel(0xbb,GPBDAT);//GPBDAT GPBDAT[7],[5:3],[1:0]=1,GPBDAT[6],[2]=0

writel(0xd,GPD0DAT);//GPD0DAT GPD0DAT[3:2],[0]=1,GPD0DAT[1]=0

writel(0xd1,GPH0DAT);//GPH0DAT[7:6],[4],[0]=1,GPH0DAT[5],[3:1]=0

writel(0xfb,GPBDAT);//GPBDAT GPBDAT[7:3],[1:0]=1,GPBDAT[2]=0

writel(0xff,GPBDAT);//GPBDAT GPBDAT[7:0]=1

writel(0x91,GPH0DAT);//GPH0DAT[7],[4],[0]=1,GPH0DAT[6:5],[3:1]=0

writel(0xd1,GPH0DAT);//GPH0DAT[7:6],[4],[0]=1,GPH0DAT[5],[3:1]=0

writel(0xd3,GPH0DAT);//GPH0DAT[7:6],[4],[1:0]=1,GPH0DAT[5],[3:2]=0

writel(0x22222222,GPF0CON);//GPF0CON set GPF0[0:7] as HSYNC,VSYNC,VDEN,VCLK,VD[0:3]

writel(0x0,GPF0PUD);//GPF0PUD set pull-up,down disable

writel(0x22222222,GPF1CON);//set GPF1CON[7:0] as VD[11:4]

writel(0x0,GPF1PUD);//GPF1PUD set pull-up,down disable

writel(0x22222222,GPF2CON);//set GPF2CON[7:0] as VD[19:12]

writel(0x0,GPF2PUD);//GPF2PUD set pull-up,down disable

writel(0x00002222,GPF3CON);//set GPF3CON[3:0] as VD[23:20]

writel(0x0,GPF3PUD);//GPF3PUD set pull-up,down disable

//--------- S5PC110 EVT0 needs MAX drive strength---------//

writel(0xffffffff,GPF0DRV);//set GPF0DRV drive strength max by WJ.KIM(09.07.17)

writel(0xffffffff,GPF1DRV);//set GPF1DRV drive strength max by WJ.KIM(09.07.17)

writel(0xffffffff,GPF2DRV);//set GPF2DRV drive strength max by WJ.KIM(09.07.17)

writel(0x3ff,GPF3DRV);//set GPF3DRV drive strength max by WJ.KIM(09.07.17)

//init gpio func for MMC

......

}

//just init some reg for enable LCD

void board_video_init(GraphicDevice *pGD)

{

DISPLAY_CONTROL_REG = 0x2;//DISPLAY_CONTROL output path RGB=FIMD I80=FIMD ITU=FIMD

CLK_SRC1_REG = 0x700000;
//CLK_SRC1 fimdclk = EPLL

}

(7)修改配置文件/include/configs/smdkv210.h如下:

#if 1

//enable LCD display

#define CONFIG_CMD_BMP

#define CONFIG_VIDEO

#define CONFIG_VIDEO_S5PC110

#define CONFIG_VIDEO_LOGO

#define VIDEO_FB_16BPP_WORD_SWAP //for BMP logo

#define CONFIG_VIDEO_SW_CURSOR

#define CONFIG_VIDEO_BMP_LOGO

//#define CONFIG_CONSOLE_EXTRA_INFO

//#define CONFIG_CONSOLE_CURSOR

//#define CONFIG_CONSOLE_TIME

#define CONFIG_CFB_CONSOLE

#define CONFIG_SYS_CONSOLE_IS_IN_ENV

//#define CFG_CONSOLE_INFO_QUIET

//#define VIDEO_FB_LITTLE_ENDIAN

#define CONFIG_SPLASH_SCREEN

#define CFG_VIDEO_LOGO_MAX_SIZE (1024*768+1024+100) /* 100 = slack */

#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (1024*768+1024+100) /* 100 = slack */

#define CONFIG_VIDEO_BMP_GZIP

#define CONFIG_CMD_UNZIP

#define LCD_VIDEO_ADDR (0x48000000)//0x57a00000

//#define LCD_VIDEO_BACKGROUND

#define CONFIG_VGA_AS_SINGLE_DEVICE

#define DEBUG_CFB_CONSOLE

#if defined(LCD_VIDEO_BACKGROUND)

#define LCD_VIDEO_BACKGROUND_ADDR (0x57900000)

#define LCD_VIDEO_BACKGROUND_LOADADDR (0x57700000)

#define LCD_VIDEO_BACKGROUND_LOADSIZE (0x40000)

#define LCD_VIDEO_BACKGROUND_ALPHA (0xa)

#define LCD_VIDEO_BACKGROUND_IN_NAND

#define LCD_VIDEO_BACKGROUND_FLASH_ADDR (0xa0000)

#endif

#define CONFIG_SYS_VIDEO_VCLOCK_HZ (133000000)

//RAM_TEXT = 0x57e00000

#endif /*enable LCD display*/

还有寄存器声明文件s5pc110.h的修改和lcd寄存器配置的文件reg-fb.h代码就不列出来了。

reg-fb.h是从内核代码中拷过来的linux/arch/arm/plat-s5p/include/plat/regs-fb.h。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: