2 * (C) Copyright 2002 ELTEC Elektronik AG
3 * Frank Gottschling <fgottschling@eltec.de>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel.
29 * At the moment only the 8x16 font is tested and the font fore- and
30 * background color is limited to black/white/gray colors. The Linux
31 * logo can be placed in the upper left corner and additional board
32 * information strings (that normally goes to serial port) can be drawn.
34 * The console driver can use the standard PC keyboard interface (i8042)
35 * for character input. Character output goes to a memory mapped video
36 * framebuffer with little or big-endian organisation.
37 * With environment setting 'console=serial' the console i/o can be
38 * forced to serial port.
40 * The driver uses graphic specific defines/parameters/functions:
42 * (for SMI LynxE graphic chip)
44 * CONFIG_VIDEO_SMI_LYNXEM - use graphic driver for SMI 710,712,810
45 * VIDEO_FB_LITTLE_ENDIAN - framebuffer organisation default: big endian
46 * VIDEO_HW_RECTFILL - graphic driver supports hardware rectangle fill
47 * VIDEO_HW_BITBLT - graphic driver supports hardware bit blt
49 * Console Parameters are set by graphic drivers global struct:
51 * VIDEO_VISIBLE_COLS - x resolution
52 * VIDEO_VISIBLE_ROWS - y resolution
53 * VIDEO_PIXEL_SIZE - storage size in byte per pixel
54 * VIDEO_DATA_FORMAT - graphical data format GDF
55 * VIDEO_FB_ADRS - start of video memory
57 * CONFIG_I8042_KBD - AT Keyboard driver for i8042
58 * VIDEO_KBD_INIT_FCT - init function for keyboard
59 * VIDEO_TSTC_FCT - keyboard_tstc function
60 * VIDEO_GETC_FCT - keyboard_getc function
62 * CONFIG_CONSOLE_CURSOR - on/off drawing cursor is done with
63 * delay loop in VIDEO_TSTC_FCT (i8042)
65 * CONFIG_SYS_CONSOLE_BLINK_COUNT - value for delay loop - blink rate
66 * CONFIG_CONSOLE_TIME - display time/date in upper right
67 * corner, needs CONFIG_CMD_DATE and
68 * CONFIG_CONSOLE_CURSOR
69 * CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner.
70 * Use CONFIG_SPLASH_SCREEN_ALIGN with
71 * environment variable "splashpos" to place
72 * the logo on other position. In this case
73 * no CONSOLE_EXTRA_INFO is possible.
74 * CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo
75 * CONFIG_CONSOLE_EXTRA_INFO - display additional board information
76 * strings that normaly goes to serial
77 * port. This define requires a board
79 * video_drawstring (VIDEO_INFO_X,
80 * VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
82 * that fills a info buffer at i=row.
83 * s.a: board/eltec/bab7xx.
84 * CONFIG_VGA_AS_SINGLE_DEVICE - If set the framebuffer device will be
85 * initialized as an output only device.
86 * The Keyboard driver will not be
87 * set-up. This may be used, if you have
88 * no or more than one Keyboard devices
89 * (USB Keyboard, AT Keyboard).
91 * CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last
92 * character. No blinking is provided.
93 * Uses the macros CURSOR_SET and
96 * CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability
97 * of the graphic chip. Uses the macro
98 * CURSOR_SET. ATTENTION: If booting an
99 * OS, the display driver must disable
100 * the hardware register of the graphic
101 * chip. Otherwise a blinking field is
108 #include <linux/compiler.h>
111 * Console device defines with SMI graphic
112 * Any other graphic must change this section
115 #ifdef CONFIG_VIDEO_SMI_LYNXEM
117 #define VIDEO_FB_LITTLE_ENDIAN
118 #define VIDEO_HW_RECTFILL
119 #define VIDEO_HW_BITBLT
123 * Defines for the CT69000 driver
125 #ifdef CONFIG_VIDEO_CT69000
127 #define VIDEO_FB_LITTLE_ENDIAN
128 #define VIDEO_HW_RECTFILL
129 #define VIDEO_HW_BITBLT
133 * Defines for the SED13806 driver
135 #ifdef CONFIG_VIDEO_SED13806
137 #ifndef CONFIG_TOTAL5200
138 #define VIDEO_FB_LITTLE_ENDIAN
140 #define VIDEO_HW_RECTFILL
141 #define VIDEO_HW_BITBLT
145 * Defines for the SED13806 driver
147 #ifdef CONFIG_VIDEO_SM501
150 #define VIDEO_FB_LITTLE_ENDIAN
154 #ifdef CONFIG_VIDEO_MXS
155 #define VIDEO_FB_16BPP_WORD_SWAP
159 * Defines for the MB862xx driver
161 #ifdef CONFIG_VIDEO_MB862xx
163 #ifdef CONFIG_VIDEO_CORALP
164 #define VIDEO_FB_LITTLE_ENDIAN
166 #ifdef CONFIG_VIDEO_MB862xx_ACCEL
167 #define VIDEO_HW_RECTFILL
168 #define VIDEO_HW_BITBLT
173 * Defines for the i.MX31 driver (mx3fb.c)
175 #if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_IPUV3)
176 #define VIDEO_FB_16BPP_WORD_SWAP
180 * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc.
182 #include <video_fb.h>
187 #define VIDEO_VISIBLE_COLS (pGD->winSizeX)
188 #define VIDEO_VISIBLE_ROWS (pGD->winSizeY)
189 #define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP)
190 #define VIDEO_DATA_FORMAT (pGD->gdfIndex)
191 #define VIDEO_FB_ADRS (pGD->frameAdrs)
194 * Console device defines with i8042 keyboard controller
195 * Any other keyboard controller must change this section
198 #ifdef CONFIG_I8042_KBD
201 #define VIDEO_KBD_INIT_FCT i8042_kbd_init()
202 #define VIDEO_TSTC_FCT i8042_tstc
203 #define VIDEO_GETC_FCT i8042_getc
211 #include <linux/types.h>
212 #include <stdio_dev.h>
213 #include <video_font.h>
214 #include <video_font_data.h>
216 #if defined(CONFIG_CMD_DATE)
220 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
221 #include <watchdog.h>
222 #include <bmp_layout.h>
224 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
225 #define BMP_ALIGN_CENTER 0x7FFF
232 * CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/input/i8042.c)
233 * to let the cursor blink. Uses the macros
234 * CURSOR_OFF and CURSOR_ON.
235 * CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No
236 * blinking is provided. Uses the macros CURSOR_SET
238 * CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the
239 * graphic chip. Uses the macro CURSOR_SET.
240 * ATTENTION: If booting an OS, the display driver
241 * must disable the hardware register of the graphic
242 * chip. Otherwise a blinking field is displayed
244 #if !defined(CONFIG_CONSOLE_CURSOR) && \
245 !defined(CONFIG_VIDEO_SW_CURSOR) && \
246 !defined(CONFIG_VIDEO_HW_CURSOR)
247 /* no Cursor defined */
253 #if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
254 #if defined(CURSOR_ON) || \
255 (defined(CONFIG_CONSOLE_CURSOR) && defined(CONFIG_VIDEO_SW_CURSOR))
256 #error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
257 or CONFIG_VIDEO_HW_CURSOR can be defined
259 void console_cursor(int state);
261 #define CURSOR_ON console_cursor(1)
262 #define CURSOR_OFF console_cursor(0)
263 #define CURSOR_SET video_set_cursor()
264 #endif /* CONFIG_CONSOLE_CURSOR || CONFIG_VIDEO_SW_CURSOR */
266 #ifdef CONFIG_CONSOLE_CURSOR
267 #ifndef CONFIG_CONSOLE_TIME
268 #error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
270 #ifndef CONFIG_I8042_KBD
271 #warning Cursor drawing on/off needs timer function s.a. drivers/input/i8042.c
273 #endif /* CONFIG_CONSOLE_CURSOR */
276 #ifdef CONFIG_VIDEO_HW_CURSOR
278 #error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
279 or CONFIG_VIDEO_HW_CURSOR can be defined
283 #define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \
284 (console_row * VIDEO_FONT_HEIGHT) + video_logo_height)
285 #endif /* CONFIG_VIDEO_HW_CURSOR */
287 #ifdef CONFIG_VIDEO_LOGO
288 #ifdef CONFIG_VIDEO_BMP_LOGO
289 #include <bmp_logo.h>
290 #include <bmp_logo_data.h>
291 #define VIDEO_LOGO_WIDTH BMP_LOGO_WIDTH
292 #define VIDEO_LOGO_HEIGHT BMP_LOGO_HEIGHT
293 #define VIDEO_LOGO_LUT_OFFSET BMP_LOGO_OFFSET
294 #define VIDEO_LOGO_COLORS BMP_LOGO_COLORS
296 #else /* CONFIG_VIDEO_BMP_LOGO */
297 #define LINUX_LOGO_WIDTH 80
298 #define LINUX_LOGO_HEIGHT 80
299 #define LINUX_LOGO_COLORS 214
300 #define LINUX_LOGO_LUT_OFFSET 0x20
302 #include <linux_logo.h>
303 #define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH
304 #define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT
305 #define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET
306 #define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS
307 #endif /* CONFIG_VIDEO_BMP_LOGO */
308 #define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
309 #define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
310 #else /* CONFIG_VIDEO_LOGO */
311 #define VIDEO_LOGO_WIDTH 0
312 #define VIDEO_LOGO_HEIGHT 0
313 #endif /* CONFIG_VIDEO_LOGO */
315 #define VIDEO_COLS VIDEO_VISIBLE_COLS
316 #define VIDEO_ROWS VIDEO_VISIBLE_ROWS
317 #define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
318 #define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2)
319 #define VIDEO_LINE_LEN (VIDEO_COLS*VIDEO_PIXEL_SIZE)
320 #define VIDEO_BURST_LEN (VIDEO_COLS/8)
322 #ifdef CONFIG_VIDEO_LOGO
323 #define CONSOLE_ROWS ((VIDEO_ROWS - video_logo_height) / VIDEO_FONT_HEIGHT)
325 #define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
328 #define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
329 #define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
330 #define CONSOLE_ROW_FIRST (video_console_address)
331 #define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
332 #define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
333 #define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
334 #define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
337 #ifdef VIDEO_FB_LITTLE_ENDIAN
338 #define SWAP16(x) ((((x) & 0x00ff) << 8) | \
341 #define SWAP32(x) ((((x) & 0x000000ff) << 24) | \
342 (((x) & 0x0000ff00) << 8) | \
343 (((x) & 0x00ff0000) >> 8) | \
344 (((x) & 0xff000000) >> 24) \
346 #define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | \
347 (((x) & 0x0000ff00) >> 8) | \
348 (((x) & 0x00ff0000) << 8) | \
349 (((x) & 0xff000000) >> 8) \
352 #define SWAP16(x) (x)
353 #define SWAP32(x) (x)
354 #if defined(VIDEO_FB_16BPP_WORD_SWAP)
355 #define SHORTSWAP32(x) (((x) >> 16) | ((x) << 16))
357 #define SHORTSWAP32(x) (x)
361 #ifdef CONFIG_CONSOLE_EXTRA_INFO
363 * setup a board string: type, speed, etc.
365 * line_number: location to place info string beside logo
366 * info: buffer for info string
368 extern void video_get_info_str(int line_number, char *info);
371 DECLARE_GLOBAL_DATA_PTR;
374 static GraphicDevice *pGD; /* Pointer to Graphic array */
376 static void *video_fb_address; /* frame buffer address */
377 static void *video_console_address; /* console buffer start address */
379 static int video_logo_height = VIDEO_LOGO_HEIGHT;
381 static int __maybe_unused cursor_state;
382 static int __maybe_unused old_col;
383 static int __maybe_unused old_row;
385 static int console_col; /* cursor col */
386 static int console_row; /* cursor row */
388 static u32 eorx, fgx, bgx; /* color pats */
390 static int cfb_do_flush_cache;
392 #ifdef CONFIG_CFB_CONSOLE_ANSI
393 static char ansi_buf[10];
394 static int ansi_buf_size;
395 static int ansi_colors_need_revert;
396 static int ansi_cursor_hidden;
399 static const int video_font_draw_table8[] = {
400 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
401 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
402 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
403 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
406 static const int video_font_draw_table15[] = {
407 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff
410 static const int video_font_draw_table16[] = {
411 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
414 static const int video_font_draw_table24[16][3] = {
415 {0x00000000, 0x00000000, 0x00000000},
416 {0x00000000, 0x00000000, 0x00ffffff},
417 {0x00000000, 0x0000ffff, 0xff000000},
418 {0x00000000, 0x0000ffff, 0xffffffff},
419 {0x000000ff, 0xffff0000, 0x00000000},
420 {0x000000ff, 0xffff0000, 0x00ffffff},
421 {0x000000ff, 0xffffffff, 0xff000000},
422 {0x000000ff, 0xffffffff, 0xffffffff},
423 {0xffffff00, 0x00000000, 0x00000000},
424 {0xffffff00, 0x00000000, 0x00ffffff},
425 {0xffffff00, 0x0000ffff, 0xff000000},
426 {0xffffff00, 0x0000ffff, 0xffffffff},
427 {0xffffffff, 0xffff0000, 0x00000000},
428 {0xffffffff, 0xffff0000, 0x00ffffff},
429 {0xffffffff, 0xffffffff, 0xff000000},
430 {0xffffffff, 0xffffffff, 0xffffffff}
433 static const int video_font_draw_table32[16][4] = {
434 {0x00000000, 0x00000000, 0x00000000, 0x00000000},
435 {0x00000000, 0x00000000, 0x00000000, 0x00ffffff},
436 {0x00000000, 0x00000000, 0x00ffffff, 0x00000000},
437 {0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff},
438 {0x00000000, 0x00ffffff, 0x00000000, 0x00000000},
439 {0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff},
440 {0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000},
441 {0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff},
442 {0x00ffffff, 0x00000000, 0x00000000, 0x00000000},
443 {0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff},
444 {0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000},
445 {0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff},
446 {0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000},
447 {0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff},
448 {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000},
449 {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}
452 static void video_drawchars(int xx, int yy, unsigned char *s, int count)
454 u8 *cdat, *dest, *dest0;
457 offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
458 dest0 = video_fb_address + offset;
460 switch (VIDEO_DATA_FORMAT) {
461 case GDF__8BIT_INDEX:
462 case GDF__8BIT_332RGB:
465 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
466 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
467 rows--; dest += VIDEO_LINE_LEN) {
471 (video_font_draw_table8[bits >> 4] &
474 (video_font_draw_table8[bits & 15] &
477 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
482 case GDF_15BIT_555RGB:
485 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
486 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
487 rows--; dest += VIDEO_LINE_LEN) {
491 SHORTSWAP32((video_font_draw_table15
492 [bits >> 6] & eorx) ^
495 SHORTSWAP32((video_font_draw_table15
496 [bits >> 4 & 3] & eorx) ^
499 SHORTSWAP32((video_font_draw_table15
500 [bits >> 2 & 3] & eorx) ^
503 SHORTSWAP32((video_font_draw_table15
507 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
512 case GDF_16BIT_565RGB:
515 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
516 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
517 rows--; dest += VIDEO_LINE_LEN) {
521 SHORTSWAP32((video_font_draw_table16
522 [bits >> 6] & eorx) ^
525 SHORTSWAP32((video_font_draw_table16
526 [bits >> 4 & 3] & eorx) ^
529 SHORTSWAP32((video_font_draw_table16
530 [bits >> 2 & 3] & eorx) ^
533 SHORTSWAP32((video_font_draw_table16
537 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
542 case GDF_32BIT_X888RGB:
545 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
546 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
547 rows--; dest += VIDEO_LINE_LEN) {
551 SWAP32((video_font_draw_table32
552 [bits >> 4][0] & eorx) ^ bgx);
554 SWAP32((video_font_draw_table32
555 [bits >> 4][1] & eorx) ^ bgx);
557 SWAP32((video_font_draw_table32
558 [bits >> 4][2] & eorx) ^ bgx);
560 SWAP32((video_font_draw_table32
561 [bits >> 4][3] & eorx) ^ bgx);
563 SWAP32((video_font_draw_table32
564 [bits & 15][0] & eorx) ^ bgx);
566 SWAP32((video_font_draw_table32
567 [bits & 15][1] & eorx) ^ bgx);
569 SWAP32((video_font_draw_table32
570 [bits & 15][2] & eorx) ^ bgx);
572 SWAP32((video_font_draw_table32
573 [bits & 15][3] & eorx) ^ bgx);
575 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
580 case GDF_24BIT_888RGB:
583 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
584 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
585 rows--; dest += VIDEO_LINE_LEN) {
589 (video_font_draw_table24[bits >> 4][0]
592 (video_font_draw_table24[bits >> 4][1]
595 (video_font_draw_table24[bits >> 4][2]
598 (video_font_draw_table24[bits & 15][0]
601 (video_font_draw_table24[bits & 15][1]
604 (video_font_draw_table24[bits & 15][2]
607 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
614 static inline void video_drawstring(int xx, int yy, unsigned char *s)
616 video_drawchars(xx, yy, s, strlen((char *) s));
619 static void video_putchar(int xx, int yy, unsigned char c)
621 video_drawchars(xx, yy + video_logo_height, &c, 1);
624 #if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
625 static void video_set_cursor(void)
632 static void video_invertchar(int xx, int yy)
634 int firstx = xx * VIDEO_PIXEL_SIZE;
635 int lastx = (xx + VIDEO_FONT_WIDTH) * VIDEO_PIXEL_SIZE;
636 int firsty = yy * VIDEO_LINE_LEN;
637 int lasty = (yy + VIDEO_FONT_HEIGHT) * VIDEO_LINE_LEN;
639 for (y = firsty; y < lasty; y += VIDEO_LINE_LEN) {
640 for (x = firstx; x < lastx; x++) {
641 u8 *dest = (u8 *)(video_fb_address) + x + y;
647 void console_cursor(int state)
649 #ifdef CONFIG_CONSOLE_TIME
653 /* time update only if cursor is on (faster scroll) */
657 sprintf(info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min,
659 video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
660 VIDEO_INFO_Y, (uchar *) info);
662 sprintf(info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon,
664 video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
665 VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT,
670 if (cursor_state != state) {
672 /* turn off the cursor */
673 video_invertchar(old_col * VIDEO_FONT_WIDTH,
674 old_row * VIDEO_FONT_HEIGHT +
677 /* turn off the cursor and record where it is */
678 video_invertchar(console_col * VIDEO_FONT_WIDTH,
679 console_row * VIDEO_FONT_HEIGHT +
681 old_col = console_col;
682 old_row = console_row;
684 cursor_state = state;
686 if (cfb_do_flush_cache)
687 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
691 #ifndef VIDEO_HW_RECTFILL
692 static void memsetl(int *p, int c, int v)
699 #ifndef VIDEO_HW_BITBLT
700 static void memcpyl(int *d, int *s, int c)
707 static void console_clear_line(int line, int begin, int end)
709 #ifdef VIDEO_HW_RECTFILL
710 video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
711 VIDEO_FONT_WIDTH * begin, /* dest pos x */
713 VIDEO_FONT_HEIGHT * line, /* dest pos y */
714 VIDEO_FONT_WIDTH * (end - begin + 1), /* fr. width */
715 VIDEO_FONT_HEIGHT, /* frame height */
719 if (begin == 0 && (end + 1) == CONSOLE_COLS) {
720 memsetl(CONSOLE_ROW_FIRST +
721 CONSOLE_ROW_SIZE * line, /* offset of row */
722 CONSOLE_ROW_SIZE >> 2, /* length of row */
729 offset = CONSOLE_ROW_FIRST +
730 CONSOLE_ROW_SIZE * line + /* offset of row */
732 VIDEO_PIXEL_SIZE * begin; /* offset of col */
733 size = VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE * (end - begin + 1);
734 size >>= 2; /* length to end for memsetl() */
735 /* fill at col offset of i'th line using bgx as fill color */
736 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
737 memsetl(offset + i * VIDEO_LINE_LEN, size, bgx);
742 static void console_scrollup(void)
744 /* copy up rows ignoring the first one */
746 #ifdef VIDEO_HW_BITBLT
747 video_hw_bitblt(VIDEO_PIXEL_SIZE, /* bytes per pixel */
748 0, /* source pos x */
750 VIDEO_FONT_HEIGHT, /* source pos y */
752 video_logo_height, /* dest pos y */
753 VIDEO_VISIBLE_COLS, /* frame width */
756 - VIDEO_FONT_HEIGHT /* frame height */
759 memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
760 CONSOLE_SCROLL_SIZE >> 2);
762 /* clear the last one */
763 console_clear_line(CONSOLE_ROWS - 1, 0, CONSOLE_COLS - 1);
766 static void console_back(void)
770 if (console_col < 0) {
771 console_col = CONSOLE_COLS - 1;
778 #ifdef CONFIG_CFB_CONSOLE_ANSI
780 static void console_clear(void)
782 #ifdef VIDEO_HW_RECTFILL
783 video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
785 video_logo_height, /* dest pos y */
786 VIDEO_VISIBLE_COLS, /* frame width */
787 VIDEO_VISIBLE_ROWS, /* frame height */
791 memsetl(CONSOLE_ROW_FIRST, CONSOLE_SIZE, bgx);
795 static void console_cursor_fix(void)
799 if (console_row >= CONSOLE_ROWS)
800 console_row = CONSOLE_ROWS - 1;
803 if (console_col >= CONSOLE_COLS)
804 console_col = CONSOLE_COLS - 1;
807 static void console_cursor_up(int n)
810 console_cursor_fix();
813 static void console_cursor_down(int n)
816 console_cursor_fix();
819 static void console_cursor_left(int n)
822 console_cursor_fix();
825 static void console_cursor_right(int n)
828 console_cursor_fix();
831 static void console_cursor_set_position(int row, int col)
833 if (console_row != -1)
835 if (console_col != -1)
837 console_cursor_fix();
840 static void console_previousline(int n)
842 /* FIXME: also scroll terminal ? */
844 console_cursor_fix();
847 static void console_swap_colors(void)
855 static inline int console_cursor_is_visible(void)
857 return !ansi_cursor_hidden;
860 static inline int console_cursor_is_visible(void)
866 static void console_newline(int n)
871 /* Check if we need to scroll the terminal */
872 if (console_row >= CONSOLE_ROWS) {
873 /* Scroll everything up */
876 /* Decrement row number */
877 console_row = CONSOLE_ROWS - 1;
881 static void console_cr(void)
886 static void parse_putc(const char c)
890 if (console_cursor_is_visible())
894 case 13: /* back to first column */
898 case '\n': /* next line */
899 if (console_col || (!console_col && nl))
905 console_col |= 0x0008;
906 console_col &= ~0x0007;
908 if (console_col >= CONSOLE_COLS)
912 case 8: /* backspace */
919 default: /* draw the char */
920 video_putchar(console_col * VIDEO_FONT_WIDTH,
921 console_row * VIDEO_FONT_HEIGHT, c);
924 /* check for newline */
925 if (console_col >= CONSOLE_COLS) {
931 if (console_cursor_is_visible())
935 void video_putc(const char c)
937 #ifdef CONFIG_CFB_CONSOLE_ANSI
941 for (i = 0; i < ansi_buf_size; ++i)
942 parse_putc(ansi_buf[i]);
948 if (ansi_buf_size > 0) {
968 ansi_buf[ansi_buf_size++] = c;
970 if (ansi_buf_size >= sizeof(ansi_buf))
973 for (i = 0; i < ansi_buf_size; ++i) {
979 if (ansi_buf[i] == 27)
986 if (ansi_buf[i] == '[')
993 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
994 num1 = ansi_buf[i]-'0';
996 } else if (ansi_buf[i] != '?') {
1004 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
1006 num1 += ansi_buf[i]-'0';
1014 if (ansi_buf[i] != ';') {
1022 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
1023 num2 = ansi_buf[i]-'0';
1030 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
1032 num2 += ansi_buf[i]-'0';
1040 if ((ansi_buf[i] >= 'A' && ansi_buf[i] <= 'H')
1041 || ansi_buf[i] == 'J'
1042 || ansi_buf[i] == 'K'
1043 || ansi_buf[i] == 'h'
1044 || ansi_buf[i] == 'l'
1045 || ansi_buf[i] == 'm') {
1046 cchar = ansi_buf[i];
1055 for (i = 0; i < ansi_buf_size; ++i)
1056 parse_putc(ansi_buf[i]);
1062 if (!ansi_cursor_hidden)
1067 /* move cursor num1 rows up */
1068 console_cursor_up(num1);
1071 /* move cursor num1 rows down */
1072 console_cursor_down(num1);
1075 /* move cursor num1 columns forward */
1076 console_cursor_right(num1);
1079 /* move cursor num1 columns back */
1080 console_cursor_left(num1);
1083 /* move cursor num1 rows up at begin of row */
1084 console_previousline(num1);
1087 /* move cursor num1 rows down at begin of row */
1088 console_newline(num1);
1091 /* move cursor to column num1 */
1092 console_cursor_set_position(-1, num1-1);
1095 /* move cursor to row num1, column num2 */
1096 console_cursor_set_position(num1-1, num2-1);
1099 /* clear console and move cursor to 0, 0 */
1101 console_cursor_set_position(0, 0);
1106 console_clear_line(console_row,
1110 console_clear_line(console_row,
1113 console_clear_line(console_row,
1117 ansi_cursor_hidden = 0;
1120 ansi_cursor_hidden = 1;
1123 if (num1 == 0) { /* reset swapped colors */
1124 if (ansi_colors_need_revert) {
1125 console_swap_colors();
1126 ansi_colors_need_revert = 0;
1128 } else if (num1 == 7) { /* once swap colors */
1129 if (!ansi_colors_need_revert) {
1130 console_swap_colors();
1131 ansi_colors_need_revert = 1;
1136 if (!ansi_cursor_hidden)
1145 if (cfb_do_flush_cache)
1146 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
1149 void video_puts(const char *s)
1151 int count = strlen(s);
1158 * Do not enforce drivers (or board code) to provide empty
1159 * video_set_lut() if they do not support 8 bpp format.
1160 * Implement weak default function instead.
1162 void __video_set_lut(unsigned int index, unsigned char r,
1163 unsigned char g, unsigned char b)
1167 void video_set_lut(unsigned int, unsigned char, unsigned char, unsigned char)
1168 __attribute__ ((weak, alias("__video_set_lut")));
1170 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
1172 #define FILL_8BIT_332RGB(r,g,b) { \
1173 *fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \
1177 #define FILL_15BIT_555RGB(r,g,b) { \
1178 *(unsigned short *)fb = \
1179 SWAP16((unsigned short)(((r>>3)<<10) | \
1185 #define FILL_16BIT_565RGB(r,g,b) { \
1186 *(unsigned short *)fb = \
1187 SWAP16((unsigned short)((((r)>>3)<<11)| \
1193 #define FILL_32BIT_X888RGB(r,g,b) { \
1194 *(unsigned long *)fb = \
1195 SWAP32((unsigned long)(((r<<16) | \
1201 #ifdef VIDEO_FB_LITTLE_ENDIAN
1202 #define FILL_24BIT_888RGB(r,g,b) { \
1209 #define FILL_24BIT_888RGB(r,g,b) { \
1217 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1218 static inline void fill_555rgb_pswap(uchar *fb, int x, u8 r, u8 g, u8 b)
1220 ushort *dst = (ushort *) fb;
1221 ushort color = (ushort) (((r >> 3) << 10) |
1232 * RLE8 bitmap support
1235 #ifdef CONFIG_VIDEO_BMP_RLE8
1236 /* Pre-calculated color table entry */
1239 unsigned short w; /* word */
1240 unsigned int dw; /* double word */
1241 } ce; /* color entry */
1245 * Helper to draw encoded/unencoded run.
1247 static void draw_bitmap(uchar **fb, uchar *bm, struct palette *p,
1250 ulong addr = (ulong) *fb;
1256 * Setup offset of the color index in the bitmap.
1257 * Color index of encoded run is at offset 1.
1259 off = enc ? &enc_off : &i;
1261 switch (VIDEO_DATA_FORMAT) {
1262 case GDF__8BIT_INDEX:
1263 for (i = 0; i < cnt; i++)
1264 *(unsigned char *) addr++ = bm[*off];
1266 case GDF_15BIT_555RGB:
1267 case GDF_16BIT_565RGB:
1268 /* differences handled while pre-calculating palette */
1269 for (i = 0; i < cnt; i++) {
1270 *(unsigned short *) addr = p[bm[*off]].ce.w;
1274 case GDF_32BIT_X888RGB:
1275 for (i = 0; i < cnt; i++) {
1276 *(unsigned long *) addr = p[bm[*off]].ce.dw;
1281 *fb = (uchar *) addr; /* return modified address */
1284 static int display_rle8_bitmap(bmp_image_t *img, int xoff, int yoff,
1285 int width, int height)
1289 unsigned int cnt, runlen;
1291 int x, y, bpp, i, ncolors;
1292 struct palette p[256];
1293 bmp_color_table_entry_t cte;
1294 int green_shift, red_off;
1295 int limit = VIDEO_COLS * VIDEO_ROWS;
1299 y = __le32_to_cpu(img->header.height) - 1;
1300 ncolors = __le32_to_cpu(img->header.colors_used);
1301 bpp = VIDEO_PIXEL_SIZE;
1302 fbp = (unsigned char *) ((unsigned int) video_fb_address +
1303 (((y + yoff) * VIDEO_COLS) + xoff) * bpp);
1305 bm = (uchar *) img + __le32_to_cpu(img->header.data_offset);
1307 /* pre-calculate and setup palette */
1308 switch (VIDEO_DATA_FORMAT) {
1309 case GDF__8BIT_INDEX:
1310 for (i = 0; i < ncolors; i++) {
1311 cte = img->color_table[i];
1312 video_set_lut(i, cte.red, cte.green, cte.blue);
1315 case GDF_15BIT_555RGB:
1316 case GDF_16BIT_565RGB:
1317 if (VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) {
1324 for (i = 0; i < ncolors; i++) {
1325 cte = img->color_table[i];
1326 p[i].ce.w = SWAP16((unsigned short)
1327 (((cte.red >> 3) << red_off) |
1328 ((cte.green >> green_shift) << 5) |
1332 case GDF_32BIT_X888RGB:
1333 for (i = 0; i < ncolors; i++) {
1334 cte = img->color_table[i];
1335 p[i].ce.dw = SWAP32((cte.red << 16) |
1341 printf("RLE Bitmap unsupported in video mode 0x%x\n",
1351 /* scan line end marker */
1355 fbp = (unsigned char *)
1356 ((unsigned int) video_fb_address +
1357 (((y + yoff) * VIDEO_COLS) +
1361 /* end of bitmap data marker */
1365 /* run offset marker */
1368 fbp = (unsigned char *)
1369 ((unsigned int) video_fb_address +
1370 (((y + yoff) * VIDEO_COLS) +
1388 if (x + runlen > width)
1390 draw_bitmap(&fbp, bm, p, cnt, 0);
1396 bm++; /* 0 padding if length is odd */
1407 if (y < height) { /* only draw into visible area */
1413 if (x + runlen > width)
1415 draw_bitmap(&fbp, bm, p, cnt, 1);
1424 printf("Error: Too much encoded pixel data, validate your bitmap\n");
1430 * Display the BMP file located at address bmp_image.
1432 int video_display_bitmap(ulong bmp_image, int x, int y)
1434 ushort xcount, ycount;
1436 bmp_image_t *bmp = (bmp_image_t *) bmp_image;
1439 unsigned long width, height, bpp;
1441 unsigned long compression;
1442 bmp_color_table_entry_t cte;
1444 #ifdef CONFIG_VIDEO_BMP_GZIP
1445 unsigned char *dst = NULL;
1451 if (!((bmp->header.signature[0] == 'B') &&
1452 (bmp->header.signature[1] == 'M'))) {
1454 #ifdef CONFIG_VIDEO_BMP_GZIP
1456 * Could be a gzipped bmp image, try to decrompress...
1458 len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
1459 dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
1461 printf("Error: malloc in gunzip failed!\n");
1464 if (gunzip(dst, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE,
1465 (uchar *) bmp_image,
1467 printf("Error: no valid bmp or bmp.gz image at %lx\n",
1472 if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
1473 printf("Image could be truncated "
1474 "(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
1478 * Set addr to decompressed image
1480 bmp = (bmp_image_t *) dst;
1482 if (!((bmp->header.signature[0] == 'B') &&
1483 (bmp->header.signature[1] == 'M'))) {
1484 printf("Error: no valid bmp.gz image at %lx\n",
1490 printf("Error: no valid bmp image at %lx\n", bmp_image);
1492 #endif /* CONFIG_VIDEO_BMP_GZIP */
1495 width = le32_to_cpu(bmp->header.width);
1496 height = le32_to_cpu(bmp->header.height);
1497 bpp = le16_to_cpu(bmp->header.bit_count);
1498 colors = le32_to_cpu(bmp->header.colors_used);
1499 compression = le32_to_cpu(bmp->header.compression);
1501 debug("Display-bmp: %ld x %ld with %d colors\n",
1502 width, height, colors);
1504 if (compression != BMP_BI_RGB
1505 #ifdef CONFIG_VIDEO_BMP_RLE8
1506 && compression != BMP_BI_RLE8
1509 printf("Error: compression type %ld not supported\n",
1511 #ifdef CONFIG_VIDEO_BMP_GZIP
1518 padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
1520 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
1521 if (x == BMP_ALIGN_CENTER)
1522 x = max(0, (VIDEO_VISIBLE_COLS - width) / 2);
1524 x = max(0, VIDEO_VISIBLE_COLS - width + x + 1);
1526 if (y == BMP_ALIGN_CENTER)
1527 y = max(0, (VIDEO_VISIBLE_ROWS - height) / 2);
1529 y = max(0, VIDEO_VISIBLE_ROWS - height + y + 1);
1530 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
1533 * Just ignore elements which are completely beyond screen
1536 if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS))
1539 if ((x + width) > VIDEO_VISIBLE_COLS)
1540 width = VIDEO_VISIBLE_COLS - x;
1541 if ((y + height) > VIDEO_VISIBLE_ROWS)
1542 height = VIDEO_VISIBLE_ROWS - y;
1544 bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
1545 fb = (uchar *) (video_fb_address +
1546 ((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) +
1547 x * VIDEO_PIXEL_SIZE);
1549 #ifdef CONFIG_VIDEO_BMP_RLE8
1550 if (compression == BMP_BI_RLE8) {
1551 return display_rle8_bitmap(bmp, x, y, width, height);
1555 /* We handle only 4, 8, or 24 bpp bitmaps */
1556 switch (le16_to_cpu(bmp->header.bit_count)) {
1558 padded_line -= width / 2;
1561 switch (VIDEO_DATA_FORMAT) {
1562 case GDF_32BIT_X888RGB:
1566 * Don't assume that 'width' is an
1569 for (xcount = 0; xcount < width; xcount++) {
1577 cte = bmp->color_table[idx];
1578 FILL_32BIT_X888RGB(cte.red, cte.green,
1581 bmap += padded_line;
1582 fb -= (VIDEO_VISIBLE_COLS + width) *
1587 puts("4bpp bitmap unsupported with current "
1594 padded_line -= width;
1595 if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
1597 for (xcount = 0; xcount < colors; ++xcount) {
1598 cte = bmp->color_table[xcount];
1599 video_set_lut(xcount, cte.red, cte.green,
1604 switch (VIDEO_DATA_FORMAT) {
1605 case GDF__8BIT_INDEX:
1612 bmap += padded_line;
1613 fb -= (VIDEO_VISIBLE_COLS + width) *
1617 case GDF__8BIT_332RGB:
1622 cte = bmp->color_table[*bmap++];
1623 FILL_8BIT_332RGB(cte.red, cte.green,
1626 bmap += padded_line;
1627 fb -= (VIDEO_VISIBLE_COLS + width) *
1631 case GDF_15BIT_555RGB:
1633 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1639 cte = bmp->color_table[*bmap++];
1640 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1641 fill_555rgb_pswap(fb, xpos++, cte.red,
1646 FILL_15BIT_555RGB(cte.red, cte.green,
1650 bmap += padded_line;
1651 fb -= (VIDEO_VISIBLE_COLS + width) *
1655 case GDF_16BIT_565RGB:
1660 cte = bmp->color_table[*bmap++];
1661 FILL_16BIT_565RGB(cte.red, cte.green,
1664 bmap += padded_line;
1665 fb -= (VIDEO_VISIBLE_COLS + width) *
1669 case GDF_32BIT_X888RGB:
1674 cte = bmp->color_table[*bmap++];
1675 FILL_32BIT_X888RGB(cte.red, cte.green,
1678 bmap += padded_line;
1679 fb -= (VIDEO_VISIBLE_COLS + width) *
1683 case GDF_24BIT_888RGB:
1688 cte = bmp->color_table[*bmap++];
1689 FILL_24BIT_888RGB(cte.red, cte.green,
1692 bmap += padded_line;
1693 fb -= (VIDEO_VISIBLE_COLS + width) *
1700 padded_line -= 3 * width;
1702 switch (VIDEO_DATA_FORMAT) {
1703 case GDF__8BIT_332RGB:
1708 FILL_8BIT_332RGB(bmap[2], bmap[1],
1712 bmap += padded_line;
1713 fb -= (VIDEO_VISIBLE_COLS + width) *
1717 case GDF_15BIT_555RGB:
1719 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1725 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1726 fill_555rgb_pswap(fb, xpos++, bmap[2],
1730 FILL_15BIT_555RGB(bmap[2], bmap[1],
1735 bmap += padded_line;
1736 fb -= (VIDEO_VISIBLE_COLS + width) *
1740 case GDF_16BIT_565RGB:
1745 FILL_16BIT_565RGB(bmap[2], bmap[1],
1749 bmap += padded_line;
1750 fb -= (VIDEO_VISIBLE_COLS + width) *
1754 case GDF_32BIT_X888RGB:
1759 FILL_32BIT_X888RGB(bmap[2], bmap[1],
1763 bmap += padded_line;
1764 fb -= (VIDEO_VISIBLE_COLS + width) *
1768 case GDF_24BIT_888RGB:
1773 FILL_24BIT_888RGB(bmap[2], bmap[1],
1777 bmap += padded_line;
1778 fb -= (VIDEO_VISIBLE_COLS + width) *
1783 printf("Error: 24 bits/pixel bitmap incompatible "
1784 "with current video mode\n");
1789 printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
1790 le16_to_cpu(bmp->header.bit_count));
1794 #ifdef CONFIG_VIDEO_BMP_GZIP
1800 if (cfb_do_flush_cache)
1801 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
1807 #ifdef CONFIG_VIDEO_LOGO
1808 static int video_logo_xpos;
1809 static int video_logo_ypos;
1811 static void plot_logo_or_black(void *screen, int width, int x, int y, \
1814 static void logo_plot(void *screen, int width, int x, int y)
1816 plot_logo_or_black(screen, width, x, y, 0);
1819 static void logo_black(void)
1821 plot_logo_or_black(video_fb_address, \
1828 static int do_clrlogo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1831 return cmd_usage(cmdtp);
1838 clrlogo, 1, 0, do_clrlogo,
1839 "fill the boot logo area with black",
1843 static void plot_logo_or_black(void *screen, int width, int x, int y, int black)
1847 int skip = (width - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
1848 int ycount = video_logo_height;
1849 unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
1850 unsigned char *source;
1851 unsigned char *dest;
1853 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
1854 if (x == BMP_ALIGN_CENTER)
1855 x = max(0, (VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH) / 2);
1857 x = max(0, VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH + x + 1);
1859 if (y == BMP_ALIGN_CENTER)
1860 y = max(0, (VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT) / 2);
1862 y = max(0, VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1);
1863 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
1865 dest = (unsigned char *)screen + (y * width + x) * VIDEO_PIXEL_SIZE;
1867 #ifdef CONFIG_VIDEO_BMP_LOGO
1868 source = bmp_logo_bitmap;
1870 /* Allocate temporary space for computing colormap */
1871 logo_red = malloc(BMP_LOGO_COLORS);
1872 logo_green = malloc(BMP_LOGO_COLORS);
1873 logo_blue = malloc(BMP_LOGO_COLORS);
1874 /* Compute color map */
1875 for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
1876 logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4;
1877 logo_green[i] = (bmp_logo_palette[i] & 0x00f0);
1878 logo_blue[i] = (bmp_logo_palette[i] & 0x000f) << 4;
1881 source = linux_logo;
1882 logo_red = linux_logo_red;
1883 logo_green = linux_logo_green;
1884 logo_blue = linux_logo_blue;
1887 if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
1888 for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
1889 video_set_lut(i + VIDEO_LOGO_LUT_OFFSET,
1890 logo_red[i], logo_green[i],
1896 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1899 xcount = VIDEO_LOGO_WIDTH;
1906 r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
1907 g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
1908 b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
1911 switch (VIDEO_DATA_FORMAT) {
1912 case GDF__8BIT_INDEX:
1915 case GDF__8BIT_332RGB:
1916 *dest = ((r >> 5) << 5) |
1920 case GDF_15BIT_555RGB:
1921 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1922 fill_555rgb_pswap(dest, xpos++, r, g, b);
1924 *(unsigned short *) dest =
1925 SWAP16((unsigned short) (
1931 case GDF_16BIT_565RGB:
1932 *(unsigned short *) dest =
1933 SWAP16((unsigned short) (
1938 case GDF_32BIT_X888RGB:
1939 *(unsigned long *) dest =
1940 SWAP32((unsigned long) (
1945 case GDF_24BIT_888RGB:
1946 #ifdef VIDEO_FB_LITTLE_ENDIAN
1958 dest += VIDEO_PIXEL_SIZE;
1962 #ifdef CONFIG_VIDEO_BMP_LOGO
1969 static void *video_logo(void)
1973 __maybe_unused int y_off = 0;
1974 __maybe_unused ulong addr;
1975 __maybe_unused char *s;
1977 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
1978 s = getenv("splashpos");
1981 video_logo_xpos = BMP_ALIGN_CENTER;
1983 video_logo_xpos = simple_strtol(s, NULL, 0);
1985 s = strchr(s + 1, ',');
1988 video_logo_ypos = BMP_ALIGN_CENTER;
1990 video_logo_ypos = simple_strtol(s + 1, NULL, 0);
1993 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
1995 #ifdef CONFIG_SPLASH_SCREEN
1996 s = getenv("splashimage");
1999 addr = simple_strtoul(s, NULL, 16);
2002 if (video_display_bitmap(addr,
2004 video_logo_ypos) == 0) {
2005 video_logo_height = 0;
2006 return ((void *) (video_fb_address));
2009 #endif /* CONFIG_SPLASH_SCREEN */
2011 logo_plot(video_fb_address, VIDEO_COLS,
2012 video_logo_xpos, video_logo_ypos);
2014 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
2016 * when using splashpos for video_logo, skip any info
2017 * output on video console if the logo is not at 0,0
2019 if (video_logo_xpos || video_logo_ypos) {
2021 * video_logo_height is used in text and cursor offset
2022 * calculations. Since the console is below the logo,
2023 * we need to adjust the logo height
2025 if (video_logo_ypos == BMP_ALIGN_CENTER)
2026 video_logo_height += max(0, (VIDEO_VISIBLE_ROWS - \
2027 VIDEO_LOGO_HEIGHT) / 2);
2028 else if (video_logo_ypos > 0)
2029 video_logo_height += video_logo_ypos;
2031 return video_fb_address + video_logo_height * VIDEO_LINE_LEN;
2035 sprintf(info, " %s", version_string);
2037 space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
2041 video_drawchars(VIDEO_INFO_X, VIDEO_INFO_Y,
2042 (uchar *) info, space);
2043 video_drawchars(VIDEO_INFO_X + VIDEO_FONT_WIDTH,
2044 VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
2045 (uchar *) info + space, len - space);
2048 video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);
2050 #ifdef CONFIG_CONSOLE_EXTRA_INFO
2053 ((video_logo_height -
2054 VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
2056 for (i = 1; i < n; i++) {
2057 video_get_info_str(i, info);
2063 video_drawchars(VIDEO_INFO_X,
2067 (uchar *) info, space);
2069 video_drawchars(VIDEO_INFO_X +
2074 (uchar *) info + space,
2077 video_drawstring(VIDEO_INFO_X,
2087 return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
2091 static int cfb_fb_is_in_dram(void)
2094 #if defined(CONFIG_ARM) || defined(CONFIG_AVR32) || defined(COFNIG_NDS32) || \
2095 defined(CONFIG_SANDBOX) || defined(CONFIG_X86)
2099 for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
2100 start = bd->bi_dram[i].start;
2101 end = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
2102 if ((ulong)video_fb_address >= start &&
2103 (ulong)video_fb_address < end)
2107 if ((ulong)video_fb_address >= bd->bi_memstart &&
2108 (ulong)video_fb_address < bd->bi_memstart + bd->bi_memsize)
2114 static int video_init(void)
2116 unsigned char color8;
2118 pGD = video_hw_init();
2122 video_fb_address = (void *) VIDEO_FB_ADRS;
2123 #ifdef CONFIG_VIDEO_HW_CURSOR
2124 video_init_hw_cursor(VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
2127 cfb_do_flush_cache = cfb_fb_is_in_dram() && dcache_status();
2129 /* Init drawing pats */
2130 switch (VIDEO_DATA_FORMAT) {
2131 case GDF__8BIT_INDEX:
2132 video_set_lut(0x01, CONSOLE_FG_COL, CONSOLE_FG_COL,
2134 video_set_lut(0x00, CONSOLE_BG_COL, CONSOLE_BG_COL,
2139 case GDF__8BIT_332RGB:
2140 color8 = ((CONSOLE_FG_COL & 0xe0) |
2141 ((CONSOLE_FG_COL >> 3) & 0x1c) |
2142 CONSOLE_FG_COL >> 6);
2143 fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
2145 color8 = ((CONSOLE_BG_COL & 0xe0) |
2146 ((CONSOLE_BG_COL >> 3) & 0x1c) |
2147 CONSOLE_BG_COL >> 6);
2148 bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
2151 case GDF_15BIT_555RGB:
2152 fgx = (((CONSOLE_FG_COL >> 3) << 26) |
2153 ((CONSOLE_FG_COL >> 3) << 21) |
2154 ((CONSOLE_FG_COL >> 3) << 16) |
2155 ((CONSOLE_FG_COL >> 3) << 10) |
2156 ((CONSOLE_FG_COL >> 3) << 5) |
2157 (CONSOLE_FG_COL >> 3));
2158 bgx = (((CONSOLE_BG_COL >> 3) << 26) |
2159 ((CONSOLE_BG_COL >> 3) << 21) |
2160 ((CONSOLE_BG_COL >> 3) << 16) |
2161 ((CONSOLE_BG_COL >> 3) << 10) |
2162 ((CONSOLE_BG_COL >> 3) << 5) |
2163 (CONSOLE_BG_COL >> 3));
2165 case GDF_16BIT_565RGB:
2166 fgx = (((CONSOLE_FG_COL >> 3) << 27) |
2167 ((CONSOLE_FG_COL >> 2) << 21) |
2168 ((CONSOLE_FG_COL >> 3) << 16) |
2169 ((CONSOLE_FG_COL >> 3) << 11) |
2170 ((CONSOLE_FG_COL >> 2) << 5) |
2171 (CONSOLE_FG_COL >> 3));
2172 bgx = (((CONSOLE_BG_COL >> 3) << 27) |
2173 ((CONSOLE_BG_COL >> 2) << 21) |
2174 ((CONSOLE_BG_COL >> 3) << 16) |
2175 ((CONSOLE_BG_COL >> 3) << 11) |
2176 ((CONSOLE_BG_COL >> 2) << 5) |
2177 (CONSOLE_BG_COL >> 3));
2179 case GDF_32BIT_X888RGB:
2180 fgx = (CONSOLE_FG_COL << 16) |
2181 (CONSOLE_FG_COL << 8) |
2183 bgx = (CONSOLE_BG_COL << 16) |
2184 (CONSOLE_BG_COL << 8) |
2187 case GDF_24BIT_888RGB:
2188 fgx = (CONSOLE_FG_COL << 24) |
2189 (CONSOLE_FG_COL << 16) |
2190 (CONSOLE_FG_COL << 8) |
2192 bgx = (CONSOLE_BG_COL << 24) |
2193 (CONSOLE_BG_COL << 16) |
2194 (CONSOLE_BG_COL << 8) |
2200 #ifdef CONFIG_VIDEO_LOGO
2201 /* Plot the logo and get start point of console */
2202 debug("Video: Drawing the logo ...\n");
2203 video_console_address = video_logo();
2205 video_console_address = video_fb_address;
2208 /* Initialize the console */
2212 if (cfb_do_flush_cache)
2213 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
2219 * Implement a weak default function for boards that optionally
2220 * need to skip the video initialization.
2222 int __board_video_skip(void)
2224 /* As default, don't skip test */
2228 int board_video_skip(void)
2229 __attribute__ ((weak, alias("__board_video_skip")));
2231 int drv_video_init(void)
2234 struct stdio_dev console_dev;
2236 /* Check if video initialization should be skipped */
2237 if (board_video_skip())
2240 /* Init video chip - returns with framebuffer cleared */
2241 skip_dev_init = (video_init() == -1);
2243 #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
2244 debug("KBD: Keyboard init ...\n");
2245 skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1);
2251 /* Init vga device */
2252 memset(&console_dev, 0, sizeof(console_dev));
2253 strcpy(console_dev.name, "vga");
2254 console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */
2255 console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
2256 console_dev.putc = video_putc; /* 'putc' function */
2257 console_dev.puts = video_puts; /* 'puts' function */
2258 console_dev.tstc = NULL; /* 'tstc' function */
2259 console_dev.getc = NULL; /* 'getc' function */
2261 #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
2262 /* Also init console device */
2263 console_dev.flags |= DEV_FLAGS_INPUT;
2264 console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */
2265 console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */
2266 #endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
2268 if (stdio_register(&console_dev) != 0)
2271 /* Return success */
2275 void video_position_cursor(unsigned col, unsigned row)
2277 console_col = min(col, CONSOLE_COLS - 1);
2278 console_row = min(row, CONSOLE_ROWS - 1);
2281 int video_get_pixel_width(void)
2283 return VIDEO_VISIBLE_COLS;
2286 int video_get_pixel_height(void)
2288 return VIDEO_VISIBLE_ROWS;
2291 int video_get_screen_rows(void)
2293 return CONSOLE_ROWS;
2296 int video_get_screen_columns(void)
2298 return CONSOLE_COLS;
2301 void video_clear(void)
2303 if (!video_fb_address)
2305 #ifdef VIDEO_HW_RECTFILL
2306 video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
2309 VIDEO_VISIBLE_COLS, /* frame width */
2310 VIDEO_VISIBLE_ROWS, /* frame height */
2311 bgx /* fill color */
2314 memsetl(video_fb_address,
2315 (VIDEO_VISIBLE_ROWS * VIDEO_LINE_LEN) / sizeof(int), bgx);