Commit 98f4a3df authored by Stefan Roese's avatar Stefan Roese
Browse files

Add SM501 support to HH405 board.

Add support for gzip compressed bmp's (CONFIG_VIDEO_BMP_GZIP).
Add support for eeprom write-enable (CFG_EEPROM_WREN).
Patch by Stefan Roese, 22 Sep 2005
parent 5810dc3a
......@@ -2,6 +2,11 @@
Changes for U-Boot 1.1.4:
======================================================================
* Add SM501 support to HH405 board.
Add support for gzip compressed bmp's (CONFIG_VIDEO_BMP_GZIP).
Add support for eeprom write-enable (CFG_EEPROM_WREN).
Patch by Stefan Roese, 22 Sep 2005
* Update configuration for INKA4x0 board
* Update configuration for PM854 board
......
......@@ -960,6 +960,12 @@ The following options need to be configured:
allows for a "silent" boot where a splash screen is
loaded very quickly after power-on.
- Gzip compressed BMP image support: CONFIG_VIDEO_BMP_GZIP
If this option is set, additionally to standard BMP
images, gzipped BMP images can be displayed via the
splashscreen support or the bmp command.
- Compression support:
CONFIG_BZIP2
......
......@@ -2,6 +2,9 @@
* (C) Copyright 2003-2004
* Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
*
* (C) Copyright 2005
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
......@@ -24,9 +27,14 @@
#include "lcd.h"
extern int video_display_bitmap (ulong, int, int);
int palette_index;
int palette_value;
int lcd_depth;
unsigned char *glob_lcd_reg;
unsigned char *glob_lcd_mem;
#ifdef CFG_LCD_ENDIAN
void lcd_setup(int lcd, int config)
......@@ -67,12 +75,9 @@ void lcd_setup(int lcd, int config)
#endif /* #ifdef CFG_LCD_ENDIAN */
void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
uchar *logo_bmp, ulong len)
void lcd_bmp(uchar *logo_bmp)
{
int i;
ushort s1dReg;
uchar s1dValue;
uchar *ptr;
ushort *ptr2;
ushort val;
......@@ -83,76 +88,37 @@ void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
unsigned char *bmp;
unsigned char r, g, b;
BITMAPINFOHEADER *bm_info;
int reg_byte_swap;
ulong len;
int do_free = 0;
/*
* Detect epson
* Check for bmp mark 'BM'
*/
if (lcd_reg[0] == 0x1c) {
/*
* Big epson detected
*/
reg_byte_swap = FALSE;
palette_index = 0x1e2;
palette_value = 0x1e4;
puts("LCD: S1D13806");
} else if (lcd_reg[1] == 0x1c) {
if (*(ushort *)logo_bmp != 0x424d) {
/*
* Big epson detected (with register swap bug)
* Decompress bmp image
*/
reg_byte_swap = TRUE;
palette_index = 0x1e3;
palette_value = 0x1e5;
puts("LCD: S1D13806S");
} else if (lcd_reg[0] == 0x18) {
len = CFG_VIDEO_LOGO_MAX_SIZE;
dst = malloc(CFG_LCD_LOGO_MAX_SIZE);
do_free = 1;
if (gunzip(dst, CFG_LCD_LOGO_MAX_SIZE, (uchar *)logo_bmp, &len) != 0) {
return;
}
/*
* Small epson detected (704)
* Check for bmp mark 'BM'
*/
reg_byte_swap = FALSE;
palette_index = 0x15;
palette_value = 0x17;
puts("LCD: S1D13704");
} else if (lcd_reg[0x10000] == 0x24) {
if (*(ushort *)dst != 0x424d) {
printf("LCD: Unknown image format!\n");
free(dst);
return;
}
} else {
/*
* Small epson detected (705)
* Uncompressed BMP image, just use this pointer
*/
reg_byte_swap = FALSE;
palette_index = 0x15;
palette_value = 0x17;
lcd_reg += 0x10000; /* add offset for 705 regs */
puts("LCD: S1D13705");
} else {
puts("LCD: No controller detected!\n");
return;
}
for (i = 0; i<reg_count; i++) {
s1dReg = regs[i].Index;
if (reg_byte_swap) {
if ((s1dReg & 0x0001) == 0)
s1dReg |= 0x0001;
else
s1dReg &= ~0x0001;
}
s1dValue = regs[i].Value;
lcd_reg[s1dReg] = s1dValue;
}
/*
* Decompress bmp image
*/
dst = malloc(CFG_LCD_LOGO_MAX_SIZE);
if (gunzip(dst, CFG_LCD_LOGO_MAX_SIZE, (uchar *)logo_bmp, &len) != 0) {
return;
}
/*
* Check for bmp mark 'BM'
*/
if (*(ushort *)dst != 0x424d) {
printf("LCD: Unknown image format!\n");
free(dst);
return;
dst = (uchar *)logo_bmp;
}
/*
......@@ -189,35 +155,48 @@ void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
/*
* Write color palette
*/
if (colors <= 256) {
if ((colors <= 256) && (lcd_depth <= 8)) {
ptr = (unsigned char *)(dst + 14 + 40);
for (i=0; i<colors; i++) {
b = *ptr++;
g = *ptr++;
r = *ptr++;
ptr++;
S1D_WRITE_PALETTE(lcd_reg, i, r, g, b);
S1D_WRITE_PALETTE(glob_lcd_reg, i, r, g, b);
}
}
/*
* Write bitmap data into framebuffer
*/
ptr = lcd_mem;
ptr2 = (ushort *)lcd_mem;
ptr = glob_lcd_mem;
ptr2 = (ushort *)glob_lcd_mem;
header_size = 14 + 40 + 4*colors; /* skip bmp header */
for (y=0; y<height; y++) {
bmp = &dst[(height-1-y)*line_size + header_size];
if (bpp == 24) {
for (x=0; x<width; x++) {
/*
* Generate epson 16bpp fb-format from 24bpp image
*/
b = *bmp++ >> 3;
g = *bmp++ >> 2;
r = *bmp++ >> 3;
val = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f);
*ptr2++ = val;
if (lcd_depth == 16) {
if (bpp == 24) {
for (x=0; x<width; x++) {
/*
* Generate epson 16bpp fb-format from 24bpp image
*/
b = *bmp++ >> 3;
g = *bmp++ >> 2;
r = *bmp++ >> 3;
val = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f);
*ptr2++ = val;
}
} else if (bpp == 8) {
for (x=0; x<line_size; x++) {
/* query rgb value from palette */
ptr = (unsigned char *)(dst + 14 + 40) ;
ptr += (*bmp++) << 2;
b = *ptr++ >> 3;
g = *ptr++ >> 2;
r = *ptr++ >> 3;
val = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f);
*ptr2++ = val;
}
}
} else {
for (x=0; x<line_size; x++) {
......@@ -226,5 +205,122 @@ void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
}
}
free(dst);
if (do_free) {
free(dst);
}
}
void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
uchar *logo_bmp, ulong len)
{
int i;
ushort s1dReg;
uchar s1dValue;
int reg_byte_swap;
/*
* Detect epson
*/
if (lcd_reg[0] == 0x1c) {
/*
* Big epson detected
*/
reg_byte_swap = FALSE;
palette_index = 0x1e2;
palette_value = 0x1e4;
lcd_depth = 16;
puts("LCD: S1D13806");
} else if (lcd_reg[1] == 0x1c) {
/*
* Big epson detected (with register swap bug)
*/
reg_byte_swap = TRUE;
palette_index = 0x1e3;
palette_value = 0x1e5;
lcd_depth = 16;
puts("LCD: S1D13806S");
} else if (lcd_reg[0] == 0x18) {
/*
* Small epson detected (704)
*/
reg_byte_swap = FALSE;
palette_index = 0x15;
palette_value = 0x17;
lcd_depth = 8;
puts("LCD: S1D13704");
} else if (lcd_reg[0x10000] == 0x24) {
/*
* Small epson detected (705)
*/
reg_byte_swap = FALSE;
palette_index = 0x15;
palette_value = 0x17;
lcd_depth = 8;
lcd_reg += 0x10000; /* add offset for 705 regs */
puts("LCD: S1D13705");
} else {
puts("LCD: No controller detected!\n");
return;
}
/*
* Setup lcd controller regs
*/
for (i = 0; i<reg_count; i++) {
s1dReg = regs[i].Index;
if (reg_byte_swap) {
if ((s1dReg & 0x0001) == 0)
s1dReg |= 0x0001;
else
s1dReg &= ~0x0001;
}
s1dValue = regs[i].Value;
lcd_reg[s1dReg] = s1dValue;
}
/*
* Save reg & mem pointer for later usage (e.g. bmp command)
*/
glob_lcd_reg = lcd_reg;
glob_lcd_mem = lcd_mem;
/*
* Display bmp image
*/
lcd_bmp(logo_bmp);
}
int do_esdbmp(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr;
char *str;
if (argc != 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
addr = simple_strtoul(argv[1], NULL, 16);
str = getenv("bd_type");
if ((strcmp(str, "ppc221") == 0) || (strcmp(str, "ppc231") == 0)) {
/*
* SM501 available, use standard bmp command
*/
return (video_display_bitmap(addr, 0, 0));
} else {
/*
* No SM501 available, use esd epson bmp command
*/
lcd_bmp((uchar *)addr);
return 0;
}
}
U_BOOT_CMD(
esdbmp, 2, 1, do_esdbmp,
"esdbmp - display BMP image\n",
"<imageAddr> - display image\n"
);
This diff is collapsed.
......@@ -2,6 +2,9 @@
* (C) Copyright 2001-2004
* Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
*
* (C) Copyright 2005
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
......@@ -25,8 +28,176 @@
#include <asm/processor.h>
#include <command.h>
#include <malloc.h>
#include <pci.h>
#include <sm501.h>
#ifdef CONFIG_VIDEO_SM501
#define SWAP32(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\
(((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) )
#ifdef CONFIG_VIDEO_SM501_8BPP
#error CONFIG_VIDEO_SM501_8BPP not supported.
#endif /* CONFIG_VIDEO_SM501_8BPP */
#ifdef CONFIG_VIDEO_SM501_16BPP
#define BPP 16
/*
* 800x600 display B084SN03: PCLK = 40MHz
* => 2*PCLK = 80MHz
* 336/4 = 84MHz
* => PCLK = 84MHz
*/
static const SMI_REGS init_regs_800x600 [] =
{
#if 1 /* test-only */
{0x0005c, SWAP32(0xffffffff)}, /* set endianess to big endian */
#else
{0x0005c, SWAP32(0x00000000)}, /* set endianess to little endian */
#endif
{0x00004, SWAP32(0x00000000)},
/* clocks for pm1... */
{0x00048, SWAP32(0x00021807)},
{0x0004C, SWAP32(0x221a0a01)},
{0x00054, SWAP32(0x00000001)},
/* clocks for pm0... */
{0x00040, SWAP32(0x00021807)},
{0x00044, SWAP32(0x221a0a01)},
{0x00054, SWAP32(0x00000000)},
/* panel control regs... */
{0x80000, SWAP32(0x0f013105)}, /* panel display control: 16-bit RGB 5:6:5 mode */
{0x80004, SWAP32(0xc428bb17)}, /* panel panning control ??? */
{0x8000C, SWAP32(0x00000000)}, /* panel fb address */
{0x80010, SWAP32(0x06400640)}, /* panel fb offset/window width */
{0x80014, SWAP32(0x03200000)}, /* panel fb width (0x320=800) */
{0x80018, SWAP32(0x02580000)}, /* panel fb height (0x258=600) */
{0x8001C, SWAP32(0x00000000)}, /* panel plane tl location */
{0x80020, SWAP32(0x02580320)}, /* panel plane br location */
{0x80024, SWAP32(0x041f031f)}, /* panel horizontal total */
{0x80028, SWAP32(0x00800347)}, /* panel horizontal sync */
{0x8002C, SWAP32(0x02730257)}, /* panel vertical total */
{0x80030, SWAP32(0x00040258)}, /* panel vertical sync */
{0x80200, SWAP32(0x00010000)}, /* crt display control */
{0, 0}
};
/*
* 1024x768 display G150XG02: PCLK = 65MHz
* => 2*PCLK = 130MHz
* 288/2 = 144MHz
* => PCLK = 72MHz
*/
static const SMI_REGS init_regs_1024x768 [] =
{
{0x00004, SWAP32(0x00000000)},
/* clocks for pm1... */
{0x00048, SWAP32(0x00021807)},
{0x0004C, SWAP32(0x011a0a01)},
{0x00054, SWAP32(0x00000001)},
/* clocks for pm0... */
{0x00040, SWAP32(0x00021807)},
{0x00044, SWAP32(0x011a0a01)},
{0x00054, SWAP32(0x00000000)},
/* panel control regs... */
{0x80000, SWAP32(0x0f013105)}, /* panel display control: 16-bit RGB 5:6:5 mode */
{0x80004, SWAP32(0xc428bb17)}, /* panel panning control ??? */
{0x8000C, SWAP32(0x00000000)}, /* panel fb address */
{0x80010, SWAP32(0x08000800)}, /* panel fb offset/window width */
{0x80014, SWAP32(0x04000000)}, /* panel fb width (0x400=1024) */
{0x80018, SWAP32(0x03000000)}, /* panel fb height (0x300=768) */
{0x8001C, SWAP32(0x00000000)}, /* panel plane tl location */
{0x80020, SWAP32(0x03000400)}, /* panel plane br location */
{0x80024, SWAP32(0x053f03ff)}, /* panel horizontal total */
{0x80028, SWAP32(0x0140040f)}, /* panel horizontal sync */
{0x8002C, SWAP32(0x032502ff)}, /* panel vertical total */
{0x80030, SWAP32(0x00260301)}, /* panel vertical sync */
{0x80200, SWAP32(0x00010000)}, /* crt display control */
{0, 0}
};
/* ------------------------------------------------------------------------- */
#endif /* CONFIG_VIDEO_SM501_16BPP */
#ifdef CONFIG_VIDEO_SM501_32BPP
#define BPP 32
/*
* 800x600 display B084SN03: PCLK = 40MHz
* => 2*PCLK = 80MHz
* 336/4 = 84MHz
* => PCLK = 84MHz
*/
static const SMI_REGS init_regs_800x600 [] =
{
#if 0 /* test-only */
{0x0005c, SWAP32(0xffffffff)}, /* set endianess to big endian */
#else
{0x0005c, SWAP32(0x00000000)}, /* set endianess to little endian */
#endif
{0x00004, SWAP32(0x00000000)},
/* clocks for pm1... */
{0x00048, SWAP32(0x00021807)},
{0x0004C, SWAP32(0x221a0a01)},
{0x00054, SWAP32(0x00000001)},
/* clocks for pm0... */
{0x00040, SWAP32(0x00021807)},
{0x00044, SWAP32(0x221a0a01)},
{0x00054, SWAP32(0x00000000)},
/* panel control regs... */
{0x80000, SWAP32(0x0f013106)}, /* panel display control: 32-bit RGB 8:8:8 mode */
{0x80004, SWAP32(0xc428bb17)}, /* panel panning control ??? */
{0x8000C, SWAP32(0x00000000)}, /* panel fb address */
{0x80010, SWAP32(0x0c800c80)}, /* panel fb offset/window width */
{0x80014, SWAP32(0x03200000)}, /* panel fb width (0x320=800) */
{0x80018, SWAP32(0x02580000)}, /* panel fb height (0x258=600) */
{0x8001C, SWAP32(0x00000000)}, /* panel plane tl location */
{0x80020, SWAP32(0x02580320)}, /* panel plane br location */
{0x80024, SWAP32(0x041f031f)}, /* panel horizontal total */
{0x80028, SWAP32(0x00800347)}, /* panel horizontal sync */
{0x8002C, SWAP32(0x02730257)}, /* panel vertical total */
{0x80030, SWAP32(0x00040258)}, /* panel vertical sync */
{0x80200, SWAP32(0x00010000)}, /* crt display control */
{0, 0}
};
/*
* 1024x768 display G150XG02: PCLK = 65MHz
* => 2*PCLK = 130MHz
* 288/2 = 144MHz
* => PCLK = 72MHz
*/
static const SMI_REGS init_regs_1024x768 [] =
{
{0x00004, SWAP32(0x00000000)},
/* clocks for pm1... */
{0x00048, SWAP32(0x00021807)},
{0x0004C, SWAP32(0x011a0a01)},
{0x00054, SWAP32(0x00000001)},
/* clocks for pm0... */
{0x00040, SWAP32(0x00021807)},
{0x00044, SWAP32(0x011a0a01)},
{0x00054, SWAP32(0x00000000)},
/* panel control regs... */
{0x80000, SWAP32(0x0f013106)}, /* panel display control: 32-bit RGB 8:8:8 mode */
{0x80004, SWAP32(0xc428bb17)}, /* panel panning control ??? */
{0x8000C, SWAP32(0x00000000)}, /* panel fb address */
{0x80010, SWAP32(0x10001000)}, /* panel fb offset/window width */
{0x80014, SWAP32(0x04000000)}, /* panel fb width (0x400=1024) */
{0x80018, SWAP32(0x03000000)}, /* panel fb height (0x300=768) */
{0x8001C, SWAP32(0x00000000)}, /* panel plane tl location */
{0x80020, SWAP32(0x03000400)}, /* panel plane br location */
{0x80024, SWAP32(0x053f03ff)}, /* panel horizontal total */
{0x80028, SWAP32(0x0140040f)}, /* panel horizontal sync */
{0x8002C, SWAP32(0x032502ff)}, /* panel vertical total */
{0x80030, SWAP32(0x00260301)}, /* panel vertical sync */
{0x80200, SWAP32(0x00010000)}, /* crt display control */
{0, 0}
};
#endif /* CONFIG_VIDEO_SM501_32BPP */
#endif /* CONFIG_VIDEO_SM501 */
#if 0
#define FPGA_DEBUG
......@@ -134,14 +305,15 @@ int board_revision(void)
if (value & 0x80000000) {
/* Revision 1.0 or 1.1 detected */
return 1;
return 0x0101;
} else {
if (value & 0x00400000) {
/* Revision 1.3 detected */
return 3;
/* unused */
return 0x0103;
} else {
/* Revision 1.2 detected */
return 2;
/* Revision >= 2.0 detected */
/* rev. 2.x uses four SM501 GPIOs for revision coding */
return 0x0200;
}
}
}
......@@ -195,6 +367,7 @@ int misc_init_r (void)
int i;
char *str;
unsigned long contrast0 = 0xffffffff;
pci_dev_t devbusfn;
dst = malloc(CFG_FPGA_MAX_SIZE);
if (gunzip (dst, CFG_FPGA_MAX_SIZE, (uchar *)fpgadata, &len) != 0) {
......@@ -261,10 +434,15 @@ int misc_init_r (void)
* Write Board revision into FPGA
*/
*fpga_ctrl |= gd->board_type & 0x0003;
if (gd->board_type >= 2) {
if (gd->board_type >= 0x0200) {
*fpga_ctrl |= CFG_FPGA_CTRL_CF_BUS_EN;
}
/*
* Setup and enable EEPROM write protection
*/
out32(GPIO0_OR, in32(GPIO0_OR) | CFG_EEPROM_WP);
/*
* Set NAND-FLASH GPIO signals to default
*/
......@@ -301,6 +479,7 @@ int misc_init_r (void)
/*
* Init lcd interface and display logo
*/
str = getenv("bd_type");
if (strcmp(str, "ppc230") == 0) {
/*
......@@ -376,8 +555,24 @@ int misc_init_r (void)
sizeof(regs_13704_320_240_4bpp)/sizeof(regs_13704_320_240_4bpp[0]),
logo_bmp_320, sizeof(logo_bmp_320));
} else {
printf("Unsupported bd_type defined (%s) -> No display configured!\n", str);
return 0;
/*
* Is SM501 connected (ppc221/ppc231)?
*/
devbusfn = pci_find_device(PCI_VENDOR_SM, PCI_DEVICE_SM501, 0);
if (devbusfn != -1) {
puts("VGA: SM501 with 8 MB ");
if (strcmp(str, "ppc221") == 0) {
printf("(800*600, %dbpp)\n", BPP);
} else if (strcmp(str, "ppc231") == 0) {
printf("(1024*768, %dbpp)\n", BPP);
} else {
printf("Unsupported bd_type defined (%s) -> No display configured!\n", str);
return 0;
}
} else {
printf("Unsupported bd_type defined (%s) -> No display configured!\n", str);
return 0;
}
}
return (0);
......@@ -410,7 +605,9 @@ int checkboard (void)
}
gd->board_type = board_revision();
printf(", Rev 1.%ld)\n", gd->board_type);
printf(", Rev %ld.%ld)\n",
(gd->board_type >> 8) & 0xff,
gd->board_type & 0xff);
/*