这里使用的是广州斯道的icool2416开发板 u-boot版本1.3.4
主要增加LCD驱动 同时增加LCD与串口同步输出
修改如下:
在drivers/video(以u-boot源码为要目录)目录下增加以下文件gzsd2416-lcd.c,gzsd2416-lcd.h和s3cfb-reg.h内容如下:
gzsd2416-lcd.c ,LCD初始化与背光控制
/*
* Gzsd2416 Framebuffer driver.
*
* Copyright 2013 Store information technology guangzhou ltd
* hclydao <[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.
*/
#include <common.h>
#include <lcd.h>
#include "gzsd2416-lcd.h"
#include <config.h>
#include <command.h>
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
vidinfo_t panel_info = {
S3CFB_HRES,
S3CFB_VRES,
0,
0,
PIXELBITS,
};
void lcd_backlight(int enable)
{
unsigned long reg;
reg = readl(GPBCON);
reg &= ~(0x3 << 0);
reg |= (0x1 << 0);
writel(reg,GPBCON);
reg = readl(GPBDAT);
if(enable)
reg |= (0x1 << 0);
else
reg &= ~(0x1 << 0);
writel(reg, GPBDAT);
}
void lcd_disable (void)
{
VIDCON0_REG &= (~(VIDCON0_ENVID_ENABLE | VIDCON0_ENVID_F_ENABLE));
}
void lcd_enable (void)
{
VIDCON0_REG |= (VIDCON0_ENVID_ENABLE | VIDCON0_ENVID_F_ENABLE);
}
void lcd_panel_disable(void)
{
//MIFPCON_REG |= SEL_BYPASS_MASK;
}
ulong calc_fbsize (void)
{
ulong size;
int line_length = (panel_info.vl_col * panel_info.vl_bpix) / 8;
size = line_length * panel_info.vl_row;
return size;
}
void lcd_ctrl_init(void *lcdbase)
{
ulong freq_lcdclk;
ulong freq_Hclk;
ulong fb_size;
unsigned char nn;
GPCCON_REG = 0xaaaa02aa;
GPCPU_REG = 0xaaaa02aa;
GPDCON_REG = 0xaaaaaaaa;
GPDPU_REG = 0xaaaaaaaa;
lcd_disable();
WINCON0_REG &= ~WINCONx_ENWIN_F_ENABLE;
WINCON1_REG &= ~WINCONx_ENWIN_F_ENABLE;
freq_lcdclk = S3CFB_PIXEL_CLOCK;
freq_Hclk = get_HCLK();
nn = (unsigned char)(freq_Hclk / freq_lcdclk) - 1;
if(freq_lcdclk < freq_Hclk/2) {
VIDCON0_REG = (VIDCON0_S_RGB_IF) | (VIDCON0_S_RGB_PAR) | (VIDCON0_S_VCLK_GATING_OFF)
| (VIDCON0_S_CLKDIR_DIVIDED) | (VIDCON0_S_CLKSEL_HCLK) | VIDCON0_CLKVAL_F(nn);
}
else {
VIDCON0_REG = (VIDCON0_S_RGB_IF) | (VIDCON0_S_RGB_PAR) | (VIDCON0_S_VCLK_GATING_OFF)
| (VIDCON0_S_CLKDIR_DIVIDED) | (VIDCON0_S_CLKSEL_HCLK) | VIDCON0_CLKVAL_F(0);
}
VIDCON1_REG = ( VIDCON1_S_HSYNC_INVERTED) | (VIDCON1_S_VSYNC_INVERTED);
VIDTCON0_REG = VIDTCON0_VBPD(S3CFB_VBP - 1) | VIDTCON0_VFPD(S3CFB_VFP - 1) | VIDTCON0_VSPW(S3CFB_VSW - 1);
VIDTCON1_REG = VIDTCON1_HBPD(S3CFB_HBP - 1) | VIDTCON1_HFPD(S3CFB_HFP - 1) | VIDTCON1_HSPW(S3CFB_HSW - 1);
VIDTCON2_REG = VIDTCON2_LINEVAL(S3CFB_VRES - 1) | VIDTCON2_HOZVAL(S3CFB_HRES - 1);
WINCON0_REG = WINCONx_BPPMODE_F_16BPP_565 | WINCONx_HAWSWP_ENABLE;
WINCON1_REG = WINCONx_BPPMODE_F_16BPP_565 | WINCONx_HAWSWP_ENABLE;// | WINCONx_BLD_PIX_PIXEL;
VIDOSD0A_REG = VIDOSDxA_OSD_LTX_F(0) | VIDOSDxA_OSD_LTY_F(0);
VIDOSD0B_REG = VIDOSDxB_OSD_RBX_F(S3CFB_HRES - 1) | VIDOSDxB_OSD_RBY_F(S3CFB_VRES - 1);
VIDOSD1A_REG = VIDOSDxA_OSD_LTX_F(0) | VIDOSDxA_OSD_LTY_F(0);
VIDOSD1B_REG = VIDOSDxB_OSD_RBX_F(S3CFB_HRES - 1) | VIDOSDxB_OSD_RBY_F(S3CFB_VRES - 1);
VIDOSD1C_REG = 0xDDD000;/*alpha blending*/
fb_size = calc_fbsize();
VIDW00ADD0B0_REG = virt_to_phys((unsigned int)lcdbase);
VIDW01ADD0_REG = virt_to_phys(osd_frame_buffer);
VIDW00ADD1B0_REG = virt_to_phys((unsigned int)lcdbase + fb_size);
VIDW01ADD1_REG = virt_to_phys(osd_frame_buffer) + fb_size;
VIDW00ADD2B0_REG = VIDWxADD2_OFFSIZE_F(0) | VIDWxADD2_PAGEWIDTH_F(S3CFB_HRES*2);
W1KEYCON0_REG = WxKEYCON0_KEYBLEN_ENABLE | WxKEYCON0_KEYEN_F_ENABLE | WxKEYCON0_COMPKEY(0xFFFF);
W1KEYCON1_REG = 0x00000000;/*color key*/
lcd_enable();
WINCON0_REG |= WINCONx_ENWIN_F_ENABLE;
WINCON1_REG |= WINCONx_ENWIN_F_ENABLE;
//run_command("fatload mmc 0 0x33d00000 logo.bin", 0);
//memset(lcdbase,0xf0,fb_size);
lcd_backlight(1);
return 0;
}
void lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
{
}
gzsd2416.h 屏幕相关参数定义#ifndef GZSD2416_LCD_H
#define GZSD2416_LCD_H
#include <config.h>
#include "s3cfb-reg.h"
#include <regs.h>
#if defined(CONFIG_LCD_NC43)
#define S3CFB_HSW 41
#define S3CFB_HBP 2
#define S3CFB_HFP 2
#define S3CFB_VSW 10
#define S3CFB_VBP 2
#define S3CFB_VFP 2
#define S3CFB_HRES 480
#define S3CFB_VRES 272
#define S3CFB_VFRAME_FREQ 60
#elif defined(CONFIG_LCD_AT070)
#define S3CFB_HSW 20
#define S3CFB_HBP 30
#define S3CFB_HFP 88
#define S3CFB_VSW 5
#define S3CFB_VBP 15
#define S3CFB_VFP 5
#define S3CFB_HRES 800
#define S3CFB_VRES 480
#define S3CFB_VFRAME_FREQ 60
#endif
#if defined(CONFIG_LCDBPP_32)
#define PIXELBITS 32
#define LCD_BPP LCD_COLOR32
#elif defined(CONFIG_LCDBPP_16)
#define PIXELBITS 16
#define LCD_BPP LCD_COLOR16
#endif
#define S3CFB_IVCLK 0//CFG_LOW
#define S3CFB_IHSYNC 1//CFG_HIGH
#define S3CFB_IVSYNC 1//CFG_HIGH
#define S3CFB_IVDEN 0//CFG_LOW
#define S3CFB_PIXEL_CLOCK (S3CFB_VFRAME_FREQ * (S3CFB_HFP + S3CFB_HSW + S3CFB_HBP + S3CFB_HRES) * (S3CFB_VFP + S3CFB_VSW + S3CFB_VBP + S3CFB_VRES))
#endif
s3cfb-reb.h LCD寄存器相关位#ifndef S3CFB_REG_H
#define S3CFB_REG_H
//rVIDCON0
#define VIDCON0_S_RGB_IF (0<<22)
#define VIDCON0_S_RGB_PAR (0<<13)
#define VIDCON0_S_VCLK_GATING_OFF (1<<5)
#define VIDCON0_S_CLKDIR_DIVIDED (1<<4)
#define VIDCON0_S_CLKSEL_HCLK (0<<2)
#define VIDCON0_ENVID_ENABLE (1 << 1)
#define VIDCON0_ENVID_F_ENABLE (1 << 0)
#define VIDCON0_CLKVAL_F(x) (((x)&0xff)<<6)
//rVIDCON1
#define VIDCON1_S_HSYNC_INVERTED (1<<6)
#define VIDCON1_S_VSYNC_INVERTED (1<<5)
//rVIDTCON0
#define VIDTCON0_VBPD(x) (((x)&0xff)<<16)
#define VIDTCON0_VFPD(x) (((x)&0xff)<<8)
#define VIDTCON0_VSPW(x) (((x)&0xff)<<0)
//rVIDTCON1
#define VIDTCON1_HBPD(x) (((x)&0xff)<<16)
#define VIDTCON1_HFPD(x) (((x)&0xff)<<8)
#define VIDTCON1_HSPW(x) (((x)&0xff)<<0)
//rVIDTCON2
#define VIDTCON2_LINEVAL(x) (((x)&0x7ff)<<11)
#define VIDTCON2_HOZVAL(x) (((x)&0x7ff)<<0)
//rWINCONx
#define WINCONx_BPPMODE_F_16BPP_565 (5 << 2)
#define WINCONx_ENWIN_F_ENABLE (1 << 0)
#define WINCONx_BLD_PIX_PIXEL (1<<6)
#define WINCONx_HAWSWP_ENABLE (1<<16)
//rVIDOSD0A
#define VIDOSDxA_OSD_LTX_F(x) (((x)&0x7ff)<<11)
#define VIDOSDxA_OSD_LTY_F(x) (((x)&0x7ff)<<0)
//rVIDOSD0B
#define VIDOSDxB_OSD_RBX_F(x) (((x)&0x7ff)<<11)
#define VIDOSDxB_OSD_RBY_F(x) (((x)&0x7ff)<<0)
//* VIDWxADD2
#define VIDWxADD2_OFFSIZE_F(x) (((x)&0x1fff)<<13)
#define VIDWxADD2_PAGEWIDTH_F(x) (((x)&0x1fff)<<0)
//WxKEYCON0
#define WxKEYCON0_KEYBLEN_ENABLE (1<<26)
#define WxKEYCON0_KEYEN_F_ENABLE (1<<25)
#define WxKEYCON0_COMPKEY(x) (((x)&0xFFFFFF)<<0)
#endif
修改当下目录下的makefile增加:
COBJS-$(CONFIG_VIDEO_GZSD2416) += gzsd2416-lcd.o
在include/configs/gzsd2416.h中增加如下定义:
//LCD
#define CONFIG_LCD 1
#define CONFIG_VIDEO_GZSD2416 1
#define CONFIG_LCD_AT070 1
#define CONFIG_LCDBPP_16 1
#define CONFIG_LCD_GZSD 1
在include/lcd.h中#if defined CONFIG_MPC823分支中增加如下几行:
#elif defined(CONFIG_LCD_GZSD)
typedef struct vidinfo {
ushort vl_col;
ushort vl_row;
ushort vl_width;
ushort vl_height;
u_char vl_bpix;
} vidinfo_t;
#define LCD_FRAMEBUFFER (TEXT_BASE - 0x300000)
#define LCD_FRAMEBUFFER_ADDR (TEXT_BASE - 0x200000)
#define LCD_MONOCHROME 0
#define LCD_COLOR2 1
#define LCD_COLOR4 2
#define LCD_COLOR8 3
#define LCD_COLOR16 4
#define LCD_COLOR32 5
extern uchar *osd_frame_buffer;
extern void lcd_backlight(int enable);
common/lcd.c修改
文件开始加入以下声明:
void *lcd_base; /* Start of framebuffer memory */
void *lcd_console_address; /* Start of console buffer */
uchar *osd_frame_buffer;
int lcd_line_length;
int lcd_color_fg;
int lcd_color_bg;
short console_col;
short console_row;
在console_scrollup函数开头加入:
#ifdef CONFIG_LCD_GZSD
lcd_console_address = (void*)osd_frame_buffer;
#endif
lcd_putc函数开头修改为如下:
#ifdef CONFIG_LCD_GZSD
serial_putc(c);
#else
if (!lcd_is_enabled) {
serial_putc(c);
return;
}
#endif
lcd_drawchars修改如下:
static void lcd_drawchars (ushort x, ushort y, uchar *str, int count)
{
uchar *dest;
ushort off, row;
#ifdef CONFIG_LCD_GZSD
dest = (uchar *)(osd_frame_buffer + y * lcd_line_length + x * (1 << LCD_BPP) / 8);
off = x * (1 << LCD_BPP) % 8;
#else
dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8);
off = x * (1 << LCD_BPP) % 8;
#endif
for (row=0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
uchar *s = str;
#ifdef CONFIG_LCD_GZSD
#if LCD_BPP == LCD_COLOR32
unsigned int *d = (unsigned int*)dest;
#elif LCD_BPP == LCD_COLOR16
ushort *d = (ushort *)dest;
#else
uchar *d = dest;
#endif
#else
uchar *d = dest;
#endif
int i;
#if LCD_BPP == LCD_MONOCHROME
uchar rest = *d & -(1 << (8-off));
uchar sym;
#endif
for (i=0; i<count; ++i) {
uchar c, bits;
c = *s++;
bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
#if LCD_BPP == LCD_MONOCHROME
sym = (COLOR_MASK(lcd_color_fg) & bits) |
(COLOR_MASK(lcd_color_bg) & ~bits);
*d++ = rest | (sym >> off);
rest = sym << (8-off);
#elif LCD_BPP == LCD_COLOR8
for (c=0; c<8; ++c) {
*d++ = (bits & 0x80) ?
lcd_color_fg : lcd_color_bg;
bits <<= 1;
}
#elif LCD_BPP == LCD_COLOR16
for (c=0; c<16; ++c) {
*d++ = (bits & 0x80) ?
lcd_color_fg : lcd_color_bg;
bits <<= 1;
}
#elif LCD_BPP == LCD_COLOR32
for (c=0; c<32; ++c) {
*d++ = (bits & 0x80) ?
lcd_color_fg : lcd_color_bg;
bits <<= 1;
}
#endif
}
#if LCD_BPP == LCD_MONOCHROME
*d = rest | (*d & ((1 << (8-off)) - 1));
#endif
}
}
drv_lcd_init修改如下:
int drv_lcd_init (void)
{
struct stdio_dev lcddev;
int rc;
#ifdef CONFIG_LCD_GZSD
lcd_base = (void*)LCD_FRAMEBUFFER_ADDR;
osd_frame_buffer=(void*)((char*)lcd_base + calc_fbsize());
lcd_line_length = (panel_info.vl_col * panel_info.vl_bpix) / 8;
#if LCD_BPP == LCD_COLOR32
lcd_color_fg = 0xFFFFFF;
lcd_color_bg = 0x000000;
#else
lcd_color_fg = 0xFFFF;
lcd_color_bg = 0x0000;
#endif
#else
lcd_base = (void *)(gd->fb_base);
lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
#endif
lcd_init (lcd_base); /* LCD initialization */
#if 1
/* Device initialization */
memset (&lcddev, 0, sizeof (lcddev));
strcpy (lcddev.name, "lcd");
lcddev.ext = 0; /* No extensions */
lcddev.flags = DEV_FLAGS_OUTPUT; /* Output only */
lcddev.putc = lcd_putc; /* 'putc' function */
lcddev.puts = lcd_puts; /* 'puts' function */
rc = stdio_register (&lcddev);
return (rc == 0) ? 1 : rc;
#else
return 1;
#endif
}
lcd_init修改如下:
static int lcd_init (void *lcdbase)
{
/* Initialize the lcd controller */
debug ("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
lcd_ctrl_init (lcdbase);
#if 0 //modify by hclydao
lcd_clear (NULL, 1, 1, NULL); /* dummy args */
lcd_enable ();
#endif
/* Initialize the console */
console_col = 0;
#ifdef CONFIG_LCD_INFO_BELOW_LOGO
console_row = 7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT;
#else
console_row = 1; /* leave 1 blank line below logo */
#endif
lcd_is_enabled = 1;
return 0;
}
效果如图:
其实还可以加一个背景图片的
感觉左边不是满屏显示 可以把HBP参数改小,关于logo显示的问题 把logo读到显存后u-boot就不往下跑了 好奇怪的现象,以前调6410 4.3寸的效果很好 换成7寸的后字体显示的也不是很漂亮了.
logo读进去其实很简单,至于不往下跑了 有兴趣的可以继续往下研究:
run_command("fatload mmc 0 0xc3c00000 logo.bin",0);
logo.bin文件可以使用Image2Lcd软件制作得到
其中0xc3c00000是显存地址,在include/lcd.h中我们定义的:
#define LCD_FRAMEBUFFER_ADDR (TEXT_BASE - 0x200000)
这个的值.