s3c2416 u-boot增加LCD驱动

这里使用的是广州斯道的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;
}

效果如图:

其实还可以加一个背景图片的

s3c2416 u-boot增加LCD驱动_第1张图片

感觉左边不是满屏显示 可以把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)
这个的值.

你可能感兴趣的:(s3c2416 u-boot增加LCD驱动)