1 //=============================================================================
5 // Frame buffer support for Dreamcast
7 //=============================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //=============================================================================
41 //#####DESCRIPTIONBEGIN####
43 // Author(s): t@keshi.org
44 // Contributors:t@keshi.org, gthomas
46 // Purpose: Red Hat/eCos banner for display during boot
48 //####DESCRIPTIONEND####
50 //=============================================================================
52 #include <pkgconf/hal.h>
54 #include <cyg/infra/diag.h>
55 #include <cyg/hal/hal_io.h> // IO macros
56 #include <cyg/hal/hal_if.h> // Virtual vector support
57 #include <cyg/hal/hal_arch.h> // Register state info
58 #include <cyg/hal/hal_intr.h> // HAL interrupt macros
64 #define RESETREG 0xa05f8008
65 #define BORDERRGB 0xa05f8040
66 #define DISPLAYMODE 0xa05f8044
67 #define ALPHAMODE 0xa05f8048
68 #define DISPLAYALIGN 0xa05f804c
69 #define BASEOFFSET1 0xa05f8050
70 #define BASEOFFSET2 0xa05f8054
71 #define DISPLAYSIZE 0xa05f805c
72 #define SYNCMODE 0xa05f80d0
73 #define VERTICALRANGE 0xa05f80dc
74 #define HORIZPOSITION 0xa05f80ec
75 #define VERTPOSITION 0xa05f80f0
76 #define PALETTEMODE 0xa05f8108
77 #define VIDEOOUTPUT 0xa0702c00
79 static unsigned long dc_parm_vga_16bpp[] = {
80 DISPLAYMODE, 0x00800005,
83 DISPLAYSIZE, (1<<20)+((480-1)<<10)+(640*2/4-1),
85 VERTPOSITION, 0x00230023,
86 VERTICALRANGE, 0x00280208,
87 HORIZPOSITION, 0x00000090,
92 static unsigned long dc_parm_vga_32bpp[] = {
93 DISPLAYMODE, 0x0080000d,
96 DISPLAYSIZE, (1<<20)+((480-1)<<10)+(640*4/4-1),
98 VERTPOSITION, 0x00230023,
99 VERTICALRANGE, 0x00280208,
100 HORIZPOSITION, 0x00000090,
105 static unsigned long *dc_parm_vga[] = {
110 static unsigned long dc_parm_composite_16bpp[] = {
111 DISPLAYMODE, 0x00000005,
114 DISPLAYSIZE, ((640*2/4+1)<<20)+((240-1)<<10)+(640*2/4-1),
116 VERTPOSITION, 0x00120012,
117 VERTICALRANGE, 0x00240204,
118 HORIZPOSITION, 0x000000a4,
123 static unsigned long dc_parm_composite_32bpp[] = {
124 DISPLAYMODE, 0x0000000d,
127 DISPLAYSIZE, ((640*4/4+1)<<20)+((240-1)<<10)+(640*4/4-1),
129 VERTPOSITION, 0x00120012,
130 VERTICALRANGE, 0x00240204,
131 HORIZPOSITION, 0x000000a4,
136 static unsigned long *dc_parm_composite[] = {
137 dc_parm_composite_16bpp,
138 dc_parm_composite_32bpp,
141 static unsigned long dc_parm_interlace_16bpp[] = {
142 DISPLAYMODE, 0x00000005,
145 DISPLAYSIZE, ((640*2/4+1)<<20)+((240-1)<<10)+(640*2/4-1),
147 VERTPOSITION, 0x00120012,
148 VERTICALRANGE, 0x00240204,
149 HORIZPOSITION, 0x000000a4,
154 static unsigned long dc_parm_interlace_32bpp[] = {
155 DISPLAYMODE, 0x0000000d,
158 DISPLAYSIZE, ((640*4/4+1)<<20)+((240-1)<<10)+(640*4/4-1),
160 VERTPOSITION, 0x00120012,
161 VERTICALRANGE, 0x00240204,
162 HORIZPOSITION, 0x000000a4,
167 static unsigned long *dc_parm_interlace[] = {
168 dc_parm_interlace_16bpp,
169 dc_parm_interlace_32bpp,
174 * 0: VGA, 2: RGB, 3: Composite
177 #define PCTRA 0xff80002c
178 #define PDTRA 0xff800030
180 static int dcfb_cable_check(void)
183 HAL_READ_UINT32(PCTRA, temp);
186 HAL_WRITE_UINT32(PCTRA, temp);
187 HAL_READ_UINT16(PDTRA, temp);
192 // Physical dimensions of LCD display
193 #define DISPLAY_WIDTH 640
194 #define DISPLAY_HEIGHT 480
196 #define LCD_WIDTH 640
197 #define LCD_HEIGHT 480
202 #define RGB_RED(x) (((x)&0x1F)<<11)
203 #define RGB_GREEN(x) (((x)&0x3F)<<5)
204 #define RGB_BLUE(x) ((x)&0x1F)
206 #define RGB_RED(x) (((x)&0x0F)<<12)
207 #define RGB_GREEN(x) (((x)&0x0F)<<7)
208 #define RGB_BLUE(x) (((x)&0x0F)<<1)
211 // Physical screen info
212 static int lcd_width = LCD_WIDTH;
213 static int lcd_height = LCD_HEIGHT;
215 // Virtual screen info
216 static int curX = 0; // Last used position
218 //static int width = LCD_WIDTH / (FONT_WIDTH*NIBBLES_PER_PIXEL);
219 //static int height = LCD_HEIGHT / (FONT_HEIGHT*SCREEN_SCALE);
221 static int fg = RGB_RED(15) | RGB_GREEN(63) | RGB_BLUE(8);
222 static int bg = RGB_RED(0) | RGB_GREEN(0) | RGB_BLUE(15/*31*/);
224 #define SCREEN_PAN 20
225 #define SCREEN_WIDTH 80
226 #define SCREEN_HEIGHT (LCD_HEIGHT/FONT_HEIGHT)
227 #define VISIBLE_SCREEN_WIDTH (LCD_WIDTH/FONT_WIDTH)
228 #define VISIBLE_SCREEN_HEIGHT (LCD_HEIGHT/FONT_HEIGHT)
229 static char screen[SCREEN_HEIGHT][SCREEN_WIDTH];
230 static int screen_start = 0;
231 static int screen_height = SCREEN_HEIGHT;
232 static int screen_width = SCREEN_WIDTH;
233 static int screen_pan = 0;
235 static bool cursor_enable = true;
239 static unsigned short *framebuffer = (void*)0xa5000000;
242 static void lcd_drawc(cyg_int8 c, int x, int y);
245 set_pixel(int row, int col, unsigned short val)
247 framebuffer[row*640+col] = val;
257 for (row = 0; row < lcd_height; row++) {
258 for (col = 0; col < lcd_width; col++) {
259 set_pixel(row, col, bg);
262 for (row = 0; row < screen_height; row++) {
263 for (col = 0; col < screen_width; col++) {
264 screen[row][col] = ' ';
267 // Note: Row 0 seems to wrap incorrectly
271 pos = (LCD_HEIGHT-1);
273 kbd_pos = show_xpm(banner_xpm, pos);
274 curX = 0; curY = screen_start;
276 lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
283 lcd_moveto(int X, int Y)
286 lcd_drawc(screen[curY][curX], curX-screen_pan, curY);
289 if (X >= screen_width) X = screen_width-1;
291 if (Y < screen_start) Y = screen_start;
292 if (Y >= screen_height) Y = screen_height-1;
295 lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
299 // Render a character at position (X,Y) with current background/foreground
301 lcd_drawc(cyg_int8 c, int x, int y)
306 if ((x < 0) || (x >= VISIBLE_SCREEN_WIDTH) ||
307 (y < 0) || (y >= screen_height)) return;
308 for (l = 0; l < FONT_HEIGHT; l++) {
309 bits = font_table[c-FIRST_CHAR][l];
310 for (p = 0; p < FONT_WIDTH; p++) {
312 set_pixel(y*FONT_HEIGHT+l, x*FONT_WIDTH + p, fg);
314 set_pixel(y*FONT_HEIGHT+l, x*FONT_WIDTH + p, bg);
326 // Now the physical screen
327 for (row = FONT_HEIGHT*(screen_start+1); row < LCD_HEIGHT; row++) {
328 p1 = &framebuffer[(row-FONT_HEIGHT)*LCD_WIDTH+0];
329 p2 = &framebuffer[row*LCD_WIDTH+0];
330 for (col = 0; col < LCD_WIDTH; col++) {
334 for (row = LCD_HEIGHT-FONT_HEIGHT; row < LCD_HEIGHT; row++) {
335 p1 = &framebuffer[row*LCD_WIDTH+0];
336 for (col = 0; col < LCD_WIDTH; col++) {
341 lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
351 // First scroll up the virtual screen
352 for (row = (screen_start+1); row < screen_height; row++) {
353 c1 = &screen[row-1][0];
354 c2 = &screen[row][0];
355 for (col = 0; col < screen_width; col++) {
359 c1 = &screen[screen_height-1][0];
360 for (col = 0; col < screen_width; col++) {
366 // Draw one character at the current position
371 lcd_drawc(screen[curY][curX], curX-screen_pan, curY);
384 if (curY < 0) curY = 0;
385 curX = screen_width-1;
389 if (((cyg_uint8)c < FIRST_CHAR) || ((cyg_uint8)c > LAST_CHAR)) c = '.';
390 screen[curY][curX] = c;
391 lcd_drawc(c, curX-screen_pan, curY);
393 if (curX == screen_width) {
398 if (curY >= screen_height) {
400 curY = (screen_height-1);
403 lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
408 lcd_setbg(int red, int green, int blue)
410 bg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
414 lcd_setfg(int red, int green, int blue)
416 fg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
420 static int _timeout = 500;
426 if ((c >= '0') && (c <= '9')) {
429 if ((c >= 'A') && (c <= 'F')) {
430 return (c - 'A') + 0x0A;
432 if ((c >= 'a') && (c <= 'f')) {
433 return (c - 'a') + 0x0a;
440 return (_hexdigit(*cp)<<4) | _hexdigit(*(cp+1));
443 static unsigned short
444 parse_color(char *cp)
446 int red, green, blue;
448 while (*cp && (*cp != 'c')) cp++;
456 return RGB_RED(red>>3) | RGB_GREEN(green>>2) | RGB_BLUE(blue>>3);
458 return RGB_RED(red>>3) | RGB_GREEN(green>>3) | RGB_BLUE(blue>>3);
469 #ifndef CYGINT_ISO_STDIO_FORMATTED_IO
477 while ((c = *cp++) && (c != ' ')) {
478 if ((c >= '0') && (c <= '9')) {
479 val = val * 10 + (c - '0');
490 show_xpm(char *xpm[], int screen_pos)
492 int i, row, col, offset;
494 int nrows, ncols, nclrs;
495 unsigned short colors[256]; // Mapped by character index
498 #ifdef CYGINT_ISO_STDIO_FORMATTED_IO
499 if (sscanf(cp, "%d %d %d", &ncols, &nrows, &nclrs) != 3) {
501 if (((ncols = get_int(&cp)) < 0) ||
502 ((nrows = get_int(&cp)) < 0) ||
503 ((nclrs = get_int(&cp)) < 0)) {
506 diag_printf("Can't parse XPM data, sorry\n");
509 // printf("%d rows, %d cols, %d colors\n", nrows, ncols, nclrs);
511 for (i = 0; i < 256; i++) {
514 for (i = 0; i < nclrs; i++) {
516 colors[(unsigned int)*cp] = parse_color(&cp[1]);
517 // printf("Color[%c] = %x\n", *cp, colors[(unsigned int)*cp]);
523 offset = screen_pos-nrows;
525 for (row = 0; row < nrows; row++) {
526 cp = xpm[nclrs+1+row];
527 for (col = 0; col < ncols; col++) {
528 set_pixel(row+offset, col, colors[(unsigned int)*cp++]);
532 screen_start = (nrows + (FONT_HEIGHT-1))/FONT_HEIGHT;
535 screen_height = offset / FONT_HEIGHT;
541 void fb_init(int depth)
543 int cable = dcfb_cable_check();
544 unsigned long **parm_list[4] = {
545 dc_parm_vga, dc_parm_vga, dc_parm_interlace, dc_parm_composite,
547 unsigned long **dc_parms = parm_list[cable];
549 unsigned long a, d, *p;
561 HAL_WRITE_UINT32(RESETREG, 0);
562 HAL_WRITE_UINT32(BORDERRGB, 0);
567 HAL_WRITE_UINT32(a, d);
575 lcd_comm_getc_nonblock(void* __ch_data, cyg_uint8* ch)
581 lcd_comm_getc(void* __ch_data)
585 while (!lcd_comm_getc_nonblock(__ch_data, &ch)) ;
590 lcd_comm_putc(void* __ch_data, cyg_uint8 c)
596 lcd_comm_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
601 lcd_comm_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
606 lcd_comm_getc_timeout(void* __ch_data, cyg_uint8* ch)
611 delay_count = _timeout * 10; // delay in .1 ms steps
613 res = lcd_comm_getc_nonblock(__ch_data, ch);
614 if (res || 0 == delay_count--)
616 CYGACC_CALL_IF_DELAY_US(100);
622 lcd_comm_control(void *__ch_data, __comm_control_cmd_t __func, ...)
627 case __COMMCTL_SET_TIMEOUT:
630 va_start(ap, __func);
632 _timeout = va_arg(ap, cyg_uint32);
636 case __COMMCTL_FLUSH_OUTPUT:
646 lcd_comm_isr(void *__ch_data, int* __ctrlc,
647 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
652 void fb_comm_init(void)
657 hal_virtual_comm_table_t* comm;
658 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
660 // Setup procs in the vector table
661 CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
662 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
663 //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
664 CYGACC_COMM_IF_WRITE_SET(*comm, lcd_comm_write);
665 CYGACC_COMM_IF_READ_SET(*comm, lcd_comm_read);
666 CYGACC_COMM_IF_PUTC_SET(*comm, lcd_comm_putc);
667 CYGACC_COMM_IF_GETC_SET(*comm, lcd_comm_getc);
668 CYGACC_COMM_IF_CONTROL_SET(*comm, lcd_comm_control);
669 CYGACC_COMM_IF_DBG_ISR_SET(*comm, lcd_comm_isr);
670 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, lcd_comm_getc_timeout);
672 // Restore original console
673 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
679 //-----------------------------------------------------------------------------
680 // End of fb_support.c