diff options
author | wdenk <wdenk> | 2002-11-03 00:24:07 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2002-11-03 00:24:07 +0000 |
commit | c609719b8d1b2dca590e0ed499016d041203e403 (patch) | |
tree | 7ea1755d80903ff972f312a249eb856061d40e15 /board/trab | |
parent | 5b1d713721c3ea02549940133f09236783dda1f9 (diff) |
Initial revision
Diffstat (limited to 'board/trab')
-rw-r--r-- | board/trab/README.kbd | 44 | ||||
-rw-r--r-- | board/trab/trab.c | 301 | ||||
-rw-r--r-- | board/trab/u-boot.lds | 63 | ||||
-rw-r--r-- | board/trab/vfd.c | 414 |
4 files changed, 822 insertions, 0 deletions
diff --git a/board/trab/README.kbd b/board/trab/README.kbd new file mode 100644 index 00000000000..3db00bccecd --- /dev/null +++ b/board/trab/README.kbd @@ -0,0 +1,44 @@ + +The TRAB keyboard implementation is similar to that for LWMON and +R360MPI boards. The only difference concerns key naming. There are 4 +keys on TRAB: 1, 2, 3, 4. + +1) The "kbd" command provides information about the current state of + the keys. For example, + + TRAB # kbd + Keys: 1 0 1 0 + + means that keys 1 and 3 are pressed. The keyboard status is also + stored in the "keybd" environment variable. In this example we get + + keybd=1010 + +2) The "preboot" variable is set according to current environment + settings and keys pressed. This is an example: + + TRAB # setenv magic_keys XY + TRAB # setenv key_magicX 12 + TRAB # setenv key_cmdX echo ## Keys 1 + 2 pressed ##\;echo + TRAB # setenv key_magicY 13 + TRAB # setenv key_cmdY echo ## Keys 1 + 3 pressed ##\;echo + + Here "magic_keys=XY" means that the "key_magicX" and "key_magicY" + variables will be checked for a match. Each variable "key_magic*" + defines a set of keys. In the our example, if keys 1 and 3 are + pressed during reset, then "key_magicY" matches, so the "preboot" + variable will be set to the contents of "key_cmdY": + + preboot=echo ## Keys 1 + 3 pressed ##;echo + +3) The TRAB board has optional modem support. When a certain key + combination is pressed on the keyboard at power-on, the firmware + performs the necessary initialization of the modem and allows for + dial-in. The key combination is specified in the + "include/configs/trab.h" file. For example: + + #define CONFIG_MODEM_KEY_MAGIC "23" + + means that modem will be initialized if and only if both keys 2, 3 + are pressed. Note that the format of this string is similar to the + format of "key_magic*" environment variables described above. diff --git a/board/trab/trab.c b/board/trab/trab.c new file mode 100644 index 00000000000..3f9b1986986 --- /dev/null +++ b/board/trab/trab.c @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* #define DEBUG */ + +#include <common.h> +#include <cmd_bsp.h> +#include <malloc.h> +#include <s3c2400.h> + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_MODEM_SUPPORT +static int key_pressed(void); +extern void disable_putc(void); +extern int do_mdm_init; /* defined in common/main.c */ + +/* + * We need a delay of at least 500 us after turning on the VFD clock + * before we can read any useful information for the CPLD controlling + * the keyboard switches. Let's play safe and wait 5 ms. The problem + * is that timers are not available yet, so we use a manually timed + * loop. + */ +#define KBD_MDELAY 100000 /* 1000 */ +static void mdelay_no_timer (int msec) +{ + DECLARE_GLOBAL_DATA_PTR; + + int i; + int delay = msec * 3; + + for (i = 0; i < delay; i ++) gd->bd->bi_arch_number = 145; +} +#endif /* CONFIG_MODEM_SUPPORT */ + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init () +{ + DECLARE_GLOBAL_DATA_PTR; + + /* memory and cpu-speed are setup before relocation */ +#ifdef CONFIG_TRAB_50MHZ + /* change the clock to be 50 MHz 1:1:1 */ + /* MDIV:0x5c PDIV:4 SDIV:2 */ + rMPLLCON = 0x5c042; + rCLKDIVN = 0; +#else + /* change the clock to be 133 MHz 1:2:4 */ + /* MDIV:0x7d PDIV:4 SDIV:1 */ + rMPLLCON = 0x7d041; + rCLKDIVN = 3; +#endif + + /* set up the I/O ports */ + rPACON = 0x3ffff; + rPBCON = 0xaaaaaaaa; + rPBUP = 0xffff; + /* INPUT nCTS0 nRTS0 TXD[1] TXD[0] RXD[1] RXD[0] */ + /* 00, 10, 10, 10, 10, 10, 10 */ + rPFCON = (2<<0) | (2<<2) | (2<<4) | (2<<6) | (2<<8) | (2<<10); +#ifdef CONFIG_HWFLOW + /* do not pull up RXD0, RXD1, TXD0, TXD1, CTS0, RTS0 */ + rPFUP = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5); +#else + /* do not pull up RXD0, RXD1, TXD0, TXD1 */ + rPFUP = (1<<0) | (1<<1) | (1<<2) | (1<<3); +#endif + rPGCON = 0x0; + rPGUP = 0x0; + rOPENCR= 0x0; + + /* arch number of SAMSUNG-Board */ + /* MACH_TYPE_SMDK2400 */ + /* XXX this isn't really correct, but keep it for now */ + gd->bd->bi_arch_number = 145; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x0c000100; + +#ifdef CONFIG_MODEM_SUPPORT + /* This stuff is needed to get interrupts on stop-position + * contact events. + * (Copied from the LCD initialization routine.) + */ + if (rLCDCON1 == 0) + { + rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA; + rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8; +#if 0 + rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA; +#endif + rLCDCON2 = 0x000DC000; + rLCDCON3 = 0x0051000A; + rLCDCON4 = 0x00000001; + rLCDCON5 = 0x00000440; + rLCDCON1 = 0x00000B75; + } + + mdelay_no_timer (KBD_MDELAY); + + if (key_pressed()) { + disable_putc(); /* modem doesn't understand banner etc */ + do_mdm_init = 1; + } +#endif /* CONFIG_MODEM_SUPPORT */ + + return 0; +} + +int dram_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + return 0; +} + +/*----------------------------------------------------------------------- + * Keyboard Controller + */ + +/* Maximum key number */ +#define KEYBD_KEY_NUM 4 + +#define KBD_DATA (((*(volatile ulong *)0x04020000) >> 16) & 0xF) + +static uchar *key_match (ulong); + +int misc_init_r (void) +{ + ulong kbd_data = KBD_DATA; + uchar keybd_env[KEYBD_KEY_NUM + 1]; + uchar *str; + int i; + + for (i = 0; i < KEYBD_KEY_NUM; ++i) { + keybd_env[i] = '0' + ((kbd_data >> i) & 1); + } + keybd_env[i] = '\0'; + debug ("** Setting keybd=\"%s\"\n", keybd_env); + setenv ("keybd", keybd_env); + + str = strdup (key_match (kbd_data)); /* decode keys */ + +#ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */ + debug ("** Setting preboot=\"%s\"\n", str); + setenv ("preboot", str); /* set or delete definition */ +#endif /* CONFIG_PREBOOT */ + if (str != NULL) { + free (str); + } + + return (0); +} + +#ifdef CONFIG_PREBOOT + +static uchar kbd_magic_prefix[] = "key_magic"; +static uchar kbd_command_prefix[] = "key_cmd"; + +static int compare_magic (ulong kbd_data, uchar *str) +{ + uchar key_mask; + + debug ("compare_magic: kbd: %04lx str: \"%s\"\n",kbd_data,str); + for (; *str; str++) + { + uchar c = *str - '1'; + + if (c >= KEYBD_KEY_NUM) /* bad key number */ + return -1; + + key_mask = 1 << c; + + if (!(kbd_data & key_mask)) { /* key not pressed */ + debug ( "compare_magic: " + "kbd: %04lx mask: %04lx - key not pressed\n", + kbd_data, key_mask ); + return -1; + } + + kbd_data &= ~key_mask; + } + + if (kbd_data) { /* key(s) not released */ + debug ( "compare_magic: " + "kbd: %04lx - key(s) not released\n", kbd_data); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------- + * Check if pressed key(s) match magic sequence, + * and return the command string associated with that key(s). + * + * If no key press was decoded, NULL is returned. + * + * Note: the first character of the argument will be overwritten with + * the "magic charcter code" of the decoded key(s), or '\0'. + * + * + * Note: the string points to static environment data and must be + * saved before you call any function that modifies the environment. + */ +static uchar *key_match (ulong kbd_data) +{ + uchar magic[sizeof (kbd_magic_prefix) + 1]; + uchar cmd_name[sizeof (kbd_command_prefix) + 1]; + uchar *suffix; + uchar *kbd_magic_keys; + + /* + * The following string defines the characters that can pe appended + * to "key_magic" to form the names of environment variables that + * hold "magic" key codes, i. e. such key codes that can cause + * pre-boot actions. If the string is empty (""), then only + * "key_magic" is checked (old behaviour); the string "125" causes + * checks for "key_magic1", "key_magic2" and "key_magic5", etc. + */ + if ((kbd_magic_keys = getenv ("magic_keys")) == NULL) + kbd_magic_keys = ""; + + debug ("key_match: magic_keys=\"%s\"\n", kbd_magic_keys); + + /* loop over all magic keys; + * use '\0' suffix in case of empty string + */ + for (suffix=kbd_magic_keys; *suffix || suffix==kbd_magic_keys; ++suffix) + { + sprintf (magic, "%s%c", kbd_magic_prefix, *suffix); + + debug ("key_match: magic=\"%s\"\n", + getenv(magic) ? getenv(magic) : "<UNDEFINED>"); + + if (compare_magic(kbd_data, getenv(magic)) == 0) + { + sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix); + debug ("key_match: cmdname %s=\"%s\"\n", + cmd_name, + getenv (cmd_name) ? + getenv (cmd_name) : + "<UNDEFINED>"); + return (getenv (cmd_name)); + } + } + debug ("key_match: no match\n"); + return (NULL); +} +#endif /* CONFIG_PREBOOT */ + +/* Read Keyboard status */ +int do_kbd (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + ulong kbd_data = KBD_DATA; + uchar keybd_env[KEYBD_KEY_NUM + 1]; + int i; + + puts ("Keys:"); + for (i = 0; i < KEYBD_KEY_NUM; ++i) { + keybd_env[i] = '0' + ((kbd_data >> i) & 1); + printf (" %c", keybd_env[i]); + } + keybd_env[i] = '\0'; + putc ('\n'); + setenv ("keybd", keybd_env); + return 0; +} + +#ifdef CONFIG_MODEM_SUPPORT +static int key_pressed(void) +{ + return (compare_magic(KBD_DATA, CONFIG_MODEM_KEY_MAGIC) == 0); +} +#endif /* CONFIG_MODEM_SUPPORT */ diff --git a/board/trab/u-boot.lds b/board/trab/u-boot.lds new file mode 100644 index 00000000000..59834afb83b --- /dev/null +++ b/board/trab/u-boot.lds @@ -0,0 +1,63 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm920t/start.o (.text) + lib_arm/_udivsi3.o (.text) + lib_arm/_umodsi3.o (.text) + lib_generic/zlib.o (.text) + lib_generic/crc32.o (.text) + lib_generic/string.o (.text) + + . = env_offset; + common/environment.o (.ppcenv) + + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/trab/vfd.c b/board/trab/vfd.c new file mode 100644 index 00000000000..1ea483f0c6b --- /dev/null +++ b/board/trab/vfd.c @@ -0,0 +1,414 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering -- wd@denx.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/************************************************************************/ +/* ** DEBUG SETTINGS */ +/************************************************************************/ + +/* #define DEBUG */ + +/************************************************************************/ +/* ** HEADER FILES */ +/************************************************************************/ + +#include <config.h> +#include <common.h> +#include <version.h> +#include <stdarg.h> +#include <linux/types.h> +#include <devices.h> +#include <s3c2400.h> + +#ifdef CONFIG_VFD + +/************************************************************************/ +/* ** CONFIG STUFF -- should be moved to board config file */ +/************************************************************************/ + +/************************************************************************/ + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +#define ROT 0x09 +#define BLAU 0x0C +#define VIOLETT 0X0D + +ulong vfdbase; +ulong frame_buf_size; +#define frame_buf_offs 4 + +/* taken from armboot/common/vfd.c */ +ulong adr_vfd_table[112][18][2][4][2]; +unsigned char bit_vfd_table[112][18][2][4][2]; + +/* + * initialize the values for the VFD-grid-control in the framebuffer + */ +void init_grid_ctrl(void) +{ + ulong adr, grid_cycle; + unsigned int bit, display; + unsigned char temp, bit_nr; + + for (adr=vfdbase; adr<=(vfdbase+7168); adr+=4) /*clear frame buffer */ + (*(volatile ulong*)(adr))=0; + + for(display=0;display<=3;display++) + { + for(grid_cycle=0;grid_cycle<=55;grid_cycle++) + { + bit = grid_cycle*256*4+(grid_cycle+200)*4+frame_buf_offs+display; + /* wrap arround if offset (see manual S3C2400) */ + if (bit>=frame_buf_size*8) + bit = bit-(frame_buf_size*8); + adr = vfdbase+(bit/32)*4+(3-(bit%32)/8); + bit_nr = bit%8; + bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + temp=(*(volatile unsigned char*)(adr)); + temp|=(1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + + if(grid_cycle<55) + bit = grid_cycle*256*4+(grid_cycle+201)*4+frame_buf_offs+display; + else + bit = grid_cycle*256*4+200*4+frame_buf_offs+display-4; /* grid nr. 0 */ + /* wrap arround if offset (see manual S3C2400) */ + if (bit>=frame_buf_size*8) + bit = bit-(frame_buf_size*8); + adr = vfdbase+(bit/32)*4+(3-(bit%32)/8); + bit_nr = bit%8; + bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + temp=(*(volatile unsigned char*)(adr)); + temp|=(1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + } + } +} + +/* + *create translation table for getting easy the right position in the + *physical framebuffer for some x/y-coordinates of the VFDs + */ +void create_vfd_table(void) +{ + unsigned int vfd_table[112][18][2][4][2]; + ulong adr; + unsigned int x, y, color, display, entry, pixel, bit_nr; + + /* + * Create translation table for Noritake-T119C-VFD-specific + * organized frame-buffer. + * Created is the number of the bit in the framebuffer (the + * first transferred pixel of each frame is bit 0). + */ + for(y=0;y<=17;y++) /* Zeile */ + { + for(x=0;x<=111;x++) /* Spalten */ + { + /*Display 0 blaue Pixel Eintrag 1 */ + vfd_table[x][y][0][0][0]=((x%4)*4+y*16+(x/4)*2048); + /*Display 0 rote Pixel Eintrag 1 */ + vfd_table[x][y][1][0][0]=((x%4)*4+y*16+(x/4)*2048+512); + if(x<=1) + { + /*Display 0 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1024); + /*Display 0 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1024); + } + else + { + /*Display 0 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+1024); + /*Display 0 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1024); + } + /*Display 1 blaue Pixel Eintrag 1 */ + vfd_table[x][y][0][1][0]=((x%4)*4+y*16+(x/4)*2048+1); + /*Display 1 rote Pixel Eintrag 1 */ + vfd_table[x][y][1][1][0]=((x%4)*4+y*16+(x/4)*2048+512+1); + if(x<=1) + { + /*Display 1 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1+1024); + /*Display 1 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1+1024); + } + else + { + /*Display 1 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+1+1024); + /*Display 1 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1+1024); + } + /*Display 2 blaue Pixel Eintrag 1 */ + vfd_table[x][y][0][2][0]=((x%4)*4+y*16+(x/4)*2048+2); + /*Display 2 rote Pixel Eintrag 1 */ + vfd_table[x][y][1][2][0]=((x%4)*4+y*16+(x/4)*2048+512+2); + if(x<=1) + { + /*Display 2 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+2+1024); + /*Display 2 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+2+1024); + } + else + { + /*Display 2 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+2+1024); + /*Display 2 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+2+1024); + } + /*Display 3 blaue Pixel Eintrag 1 */ + vfd_table[x][y][0][3][0]=((x%4)*4+y*16+(x/4)*2048+3); + /*Display 3 rote Pixel Eintrag 1 */ + vfd_table[x][y][1][3][0]=((x%4)*4+y*16+(x/4)*2048+512+3); + if(x<=1) + { + /*Display 3 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+3+1024); + /*Display 3 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+3+1024); + } + else + { + /*Display 3 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+3+1024); + /*Display 3 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+3+1024); + } + } + } + + /* + * Create translation table for Noritake-T119C-VFD-specific + * organized frame-buffer + * Create table with entries for physical byte adresses and + * bit-number within the byte + * from table with bit-numbers within the total framebuffer + */ + for(y=0;y<=17;y++) + { + for(x=0;x<=111;x++) + { + for(color=0;color<=1;color++) + { + for(display=0;display<=3;display++) + { + for(entry=0;entry<=1;entry++) + { + pixel = vfd_table[x][y][color][display][entry] + frame_buf_offs; + /* + * wrap arround if offset + * (see manual S3C2400) + */ + if (pixel>=frame_buf_size*8) + pixel = pixel-(frame_buf_size*8); + adr = vfdbase+(pixel/32)*4+(3-(pixel%32)/8); + bit_nr = pixel%8; + bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + adr_vfd_table[x][y][color][display][entry] = adr; + bit_vfd_table[x][y][color][display][entry] = bit_nr; + } + } + } + } + } +} + +/* + * Set/clear pixel of the VFDs + */ +void set_vfd_pixel(unsigned char x, unsigned char y, unsigned char color, unsigned char display, unsigned char value) +{ + ulong adr; + unsigned char bit_nr, temp; + + if (value!=0) + { + /* Pixel-Eintrag Nr. 1 */ + adr = adr_vfd_table[x][y][color][display][0]; + /* Pixel-Eintrag Nr. 1 */ + bit_nr = bit_vfd_table[x][y][color][display][0]; + temp=(*(volatile unsigned char*)(adr)); + temp|=1<<bit_nr; + (*(volatile unsigned char*)(adr))=temp; + + /* Pixel-Eintrag Nr. 2 */ + adr = adr_vfd_table[x][y][color][display][1]; + /* Pixel-Eintrag Nr. 2 */ + bit_nr = bit_vfd_table[x][y][color][display][1]; + temp=(*(volatile unsigned char*)(adr)); + temp|=1<<bit_nr; + (*(volatile unsigned char*)(adr))=temp; + } + else + { + /* Pixel-Eintrag Nr. 1 */ + adr = adr_vfd_table[x][y][color][display][0]; + /* Pixel-Eintrag Nr. 1 */ + bit_nr = bit_vfd_table[x][y][color][display][0]; + temp=(*(volatile unsigned char*)(adr)); + temp&=~(1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + + /* Pixel-Eintrag Nr. 2 */ + adr = adr_vfd_table[x][y][color][display][1]; + /* Pixel-Eintrag Nr. 2 */ + bit_nr = bit_vfd_table[x][y][color][display][1]; + temp=(*(volatile unsigned char*)(adr)); + temp&=~(1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + } +} + +/* + * transfer image from BMP-File + */ +void transfer_pic(int display, unsigned char *adr, int height, int width) +{ + int x, y; + unsigned char temp; + + for (; height > 0; height -= 18) + { + if (height > 18) + y = 18; + else + y = height; + for (; y > 0; y--) + { + for (x = 0; x < width; x += 2) + { + temp = *adr++; + set_vfd_pixel(x, y-1, 0, display, 0); + set_vfd_pixel(x, y-1, 1, display, 0); + if ((temp >> 4) == BLAU) + set_vfd_pixel(x, y-1, 0, display, 1); + else if ((temp >> 4) == ROT) + set_vfd_pixel(x, y-1, 1, display, 1); + else if ((temp >> 4) == VIOLETT) + { + set_vfd_pixel(x, y-1, 0, display, 1); + set_vfd_pixel(x, y-1, 1, display, 1); + } + set_vfd_pixel(x+1, y-1, 0, display, 0); + set_vfd_pixel(x+1, y-1, 1, display, 0); + if ((temp & 0x0F) == BLAU) + set_vfd_pixel(x+1, y-1, 0, display, 1); + else if ((temp & 0x0F) == ROT) + set_vfd_pixel(x+1, y-1, 1, display, 1); + else if ((temp & 0x0F) == VIOLETT) + { + set_vfd_pixel(x+1, y-1, 0, display, 1); + set_vfd_pixel(x+1, y-1, 1, display, 1); + } + } + } + display++; + if (display > 3) + display = 0; + } +} + +/* + * initialize LCD-Controller of the S3C2400 for using VFDs + */ +int drv_vfd_init(void) +{ + ulong palette; + + DECLARE_GLOBAL_DATA_PTR; + + vfdbase = gd->fb_base; + create_vfd_table(); + init_grid_ctrl(); + + /* + * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben + * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt + * das letzte angezeigte Pixel wird aus dem ersten Nibble geholt + * (wrap around) + * see manual S3C2400 + */ + /* frame buffer startadr */ + rLCDSADDR1 = vfdbase >> 1; + /* frame buffer endadr */ + rLCDSADDR2 = (vfdbase + frame_buf_size) >> 1; + rLCDSADDR3 = ((256/4)); + + /* Port-Pins als LCD-Ausgang */ + rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA; + /* Port-Pins als LCD-Ausgang */ + rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8; +#ifdef WITH_VFRAME + /* mit VFRAME zum Messen */ + rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA; +#endif + + rLCDCON2 = 0x000DC000; + rLCDCON3 = 0x0051000A; + rLCDCON4 = 0x00000001; + rLCDCON5 = 0x00000440; + rLCDCON1 = 0x00000B75; + + debug ("LCDSADDR1: %lX\n", rLCDSADDR1); + debug ("LCDSADDR2: %lX\n", rLCDSADDR2); + debug ("LCDSADDR3: %lX\n", rLCDSADDR3); + + for(palette=0;palette<=15;palette++) + (*(volatile unsigned int*)(PALETTE+(palette*4)))=palette; + for(palette=16;palette<=255;palette++) + (*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00; + + return 0; +} + +/************************************************************************/ +/* ** ROM capable initialization part - needed to reserve FB memory */ +/************************************************************************/ + +/* + * This is called early in the system initialization to grab memory + * for the VFD controller. + * + * Note that this is running from ROM, so no write access to global data. + */ +ulong vfd_setmem (ulong addr) +{ + ulong size; + + /* MAGIC */ + frame_buf_size = (256*4*56)/8; + + /* Round up to nearest full page */ + size = (frame_buf_size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); + + debug ("Reserving %ldk for VFD Framebuffer at: %08lx\n", size>>10, addr); + + return (size); +} + +#endif /* CONFIG_VFD */ |