2 * (C) Copyright 2002 ELTEC Elektronik AG
3 * Frank Gottschling <fgottschling@eltec.de>
5 * SPDX-License-Identifier: GPL-2.0+
11 * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel.
13 * At the moment only the 8x16 font is tested and the font fore- and
14 * background color is limited to black/white/gray colors. The Linux
15 * logo can be placed in the upper left corner and additional board
16 * information strings (that normally goes to serial port) can be drawn.
18 * The console driver can use a keyboard interface for character input
19 * but this is deprecated. Only rk51 uses it.
21 * Character output goes to a memory-mapped video
22 * framebuffer with little or big-endian organisation.
23 * With environment setting 'console=serial' the console i/o can be
24 * forced to serial port.
26 * The driver uses graphic specific defines/parameters/functions:
28 * (for SMI LynxE graphic chip)
30 * VIDEO_FB_LITTLE_ENDIAN - framebuffer organisation default: big endian
31 * VIDEO_HW_RECTFILL - graphic driver supports hardware rectangle fill
32 * VIDEO_HW_BITBLT - graphic driver supports hardware bit blt
34 * Console Parameters are set by graphic drivers global struct:
36 * VIDEO_VISIBLE_COLS - x resolution
37 * VIDEO_VISIBLE_ROWS - y resolution
38 * VIDEO_PIXEL_SIZE - storage size in byte per pixel
39 * VIDEO_DATA_FORMAT - graphical data format GDF
40 * VIDEO_FB_ADRS - start of video memory
42 * VIDEO_KBD_INIT_FCT - init function for keyboard
43 * VIDEO_TSTC_FCT - keyboard_tstc function
44 * VIDEO_GETC_FCT - keyboard_getc function
46 * CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner.
47 * Use CONFIG_SPLASH_SCREEN_ALIGN with
48 * environment variable "splashpos" to place
49 * the logo on other position. In this case
50 * no CONSOLE_EXTRA_INFO is possible.
51 * CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo
52 * CONFIG_CONSOLE_EXTRA_INFO - display additional board information
53 * strings that normaly goes to serial
54 * port. This define requires a board
56 * video_drawstring (VIDEO_INFO_X,
57 * VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
59 * that fills a info buffer at i=row.
60 * s.a: board/eltec/bab7xx.
62 * CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last
63 * character. No blinking is provided.
64 * Uses the macros CURSOR_SET and
73 #include <linux/compiler.h>
76 * Defines for the CT69000 driver
78 #ifdef CONFIG_VIDEO_CT69000
80 #define VIDEO_FB_LITTLE_ENDIAN
81 #define VIDEO_HW_RECTFILL
82 #define VIDEO_HW_BITBLT
85 #if defined(CONFIG_VIDEO_MXS)
86 #define VIDEO_FB_16BPP_WORD_SWAP
90 * Defines for the MB862xx driver
92 #ifdef CONFIG_VIDEO_MB862xx
94 #ifdef CONFIG_VIDEO_CORALP
95 #define VIDEO_FB_LITTLE_ENDIAN
97 #ifdef CONFIG_VIDEO_MB862xx_ACCEL
98 #define VIDEO_HW_RECTFILL
99 #define VIDEO_HW_BITBLT
104 * Defines for the i.MX31 driver (mx3fb.c)
106 #if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_IPUV3)
107 #define VIDEO_FB_16BPP_WORD_SWAP
111 * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc.
113 #include <video_fb.h>
120 #define VIDEO_VISIBLE_COLS (pGD->winSizeX)
121 #define VIDEO_VISIBLE_ROWS (pGD->winSizeY)
122 #define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP)
123 #define VIDEO_DATA_FORMAT (pGD->gdfIndex)
124 #define VIDEO_FB_ADRS (pGD->frameAdrs)
131 #include <linux/types.h>
132 #include <stdio_dev.h>
133 #include <video_font.h>
135 #if defined(CONFIG_CMD_DATE)
139 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
140 #include <watchdog.h>
141 #include <bmp_layout.h>
145 #if !defined(CONFIG_VIDEO_SW_CURSOR)
146 /* no Cursor defined */
152 #if defined(CONFIG_VIDEO_SW_CURSOR)
153 void console_cursor(int state);
155 #define CURSOR_ON console_cursor(1)
156 #define CURSOR_OFF console_cursor(0)
157 #define CURSOR_SET video_set_cursor()
158 #endif /* CONFIG_VIDEO_SW_CURSOR */
160 #ifdef CONFIG_VIDEO_LOGO
161 #ifdef CONFIG_VIDEO_BMP_LOGO
162 #include <bmp_logo.h>
163 #include <bmp_logo_data.h>
164 #define VIDEO_LOGO_WIDTH BMP_LOGO_WIDTH
165 #define VIDEO_LOGO_HEIGHT BMP_LOGO_HEIGHT
166 #define VIDEO_LOGO_LUT_OFFSET BMP_LOGO_OFFSET
167 #define VIDEO_LOGO_COLORS BMP_LOGO_COLORS
169 #else /* CONFIG_VIDEO_BMP_LOGO */
170 #define LINUX_LOGO_WIDTH 80
171 #define LINUX_LOGO_HEIGHT 80
172 #define LINUX_LOGO_COLORS 214
173 #define LINUX_LOGO_LUT_OFFSET 0x20
175 #include <linux_logo.h>
176 #define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH
177 #define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT
178 #define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET
179 #define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS
180 #endif /* CONFIG_VIDEO_BMP_LOGO */
181 #define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
182 #define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
183 #else /* CONFIG_VIDEO_LOGO */
184 #define VIDEO_LOGO_WIDTH 0
185 #define VIDEO_LOGO_HEIGHT 0
186 #endif /* CONFIG_VIDEO_LOGO */
188 #define VIDEO_COLS VIDEO_VISIBLE_COLS
189 #define VIDEO_ROWS VIDEO_VISIBLE_ROWS
190 #ifndef VIDEO_LINE_LEN
191 #define VIDEO_LINE_LEN (VIDEO_COLS * VIDEO_PIXEL_SIZE)
193 #define VIDEO_SIZE (VIDEO_ROWS * VIDEO_LINE_LEN)
194 #define VIDEO_BURST_LEN (VIDEO_COLS/8)
196 #ifdef CONFIG_VIDEO_LOGO
197 #define CONSOLE_ROWS ((VIDEO_ROWS - video_logo_height) / VIDEO_FONT_HEIGHT)
199 #define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
202 #define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
203 #define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
204 #define CONSOLE_ROW_FIRST (video_console_address)
205 #define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
206 #define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
207 #define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
209 /* By default we scroll by a single line */
210 #ifndef CONFIG_CONSOLE_SCROLL_LINES
211 #define CONFIG_CONSOLE_SCROLL_LINES 1
215 #ifdef VIDEO_FB_LITTLE_ENDIAN
216 #define SWAP16(x) ((((x) & 0x00ff) << 8) | \
219 #define SWAP32(x) ((((x) & 0x000000ff) << 24) | \
220 (((x) & 0x0000ff00) << 8) | \
221 (((x) & 0x00ff0000) >> 8) | \
222 (((x) & 0xff000000) >> 24) \
224 #define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | \
225 (((x) & 0x0000ff00) >> 8) | \
226 (((x) & 0x00ff0000) << 8) | \
227 (((x) & 0xff000000) >> 8) \
230 #define SWAP16(x) (x)
231 #define SWAP32(x) (x)
232 #if defined(VIDEO_FB_16BPP_WORD_SWAP)
233 #define SHORTSWAP32(x) (((x) >> 16) | ((x) << 16))
235 #define SHORTSWAP32(x) (x)
239 DECLARE_GLOBAL_DATA_PTR;
242 static GraphicDevice *pGD; /* Pointer to Graphic array */
244 static void *video_fb_address; /* frame buffer address */
245 static void *video_console_address; /* console buffer start address */
247 static int video_logo_height = VIDEO_LOGO_HEIGHT;
249 static int __maybe_unused cursor_state;
250 static int __maybe_unused old_col;
251 static int __maybe_unused old_row;
253 static int console_col; /* cursor col */
254 static int console_row; /* cursor row */
256 static u32 eorx, fgx, bgx; /* color pats */
258 static int cfb_do_flush_cache;
260 #ifdef CONFIG_CFB_CONSOLE_ANSI
261 static char ansi_buf[10];
262 static int ansi_buf_size;
263 static int ansi_colors_need_revert;
264 static int ansi_cursor_hidden;
267 static const int video_font_draw_table8[] = {
268 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
269 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
270 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
271 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
274 static const int video_font_draw_table15[] = {
275 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff
278 static const int video_font_draw_table16[] = {
279 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
282 static const int video_font_draw_table24[16][3] = {
283 {0x00000000, 0x00000000, 0x00000000},
284 {0x00000000, 0x00000000, 0x00ffffff},
285 {0x00000000, 0x0000ffff, 0xff000000},
286 {0x00000000, 0x0000ffff, 0xffffffff},
287 {0x000000ff, 0xffff0000, 0x00000000},
288 {0x000000ff, 0xffff0000, 0x00ffffff},
289 {0x000000ff, 0xffffffff, 0xff000000},
290 {0x000000ff, 0xffffffff, 0xffffffff},
291 {0xffffff00, 0x00000000, 0x00000000},
292 {0xffffff00, 0x00000000, 0x00ffffff},
293 {0xffffff00, 0x0000ffff, 0xff000000},
294 {0xffffff00, 0x0000ffff, 0xffffffff},
295 {0xffffffff, 0xffff0000, 0x00000000},
296 {0xffffffff, 0xffff0000, 0x00ffffff},
297 {0xffffffff, 0xffffffff, 0xff000000},
298 {0xffffffff, 0xffffffff, 0xffffffff}
301 static const int video_font_draw_table32[16][4] = {
302 {0x00000000, 0x00000000, 0x00000000, 0x00000000},
303 {0x00000000, 0x00000000, 0x00000000, 0x00ffffff},
304 {0x00000000, 0x00000000, 0x00ffffff, 0x00000000},
305 {0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff},
306 {0x00000000, 0x00ffffff, 0x00000000, 0x00000000},
307 {0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff},
308 {0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000},
309 {0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff},
310 {0x00ffffff, 0x00000000, 0x00000000, 0x00000000},
311 {0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff},
312 {0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000},
313 {0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff},
314 {0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000},
315 {0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff},
316 {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000},
317 {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}
321 * Implement a weak default function for boards that optionally
322 * need to skip the cfb initialization.
324 __weak int board_cfb_skip(void)
326 /* As default, don't skip cfb init */
330 static void video_drawchars(int xx, int yy, unsigned char *s, int count)
332 u8 *cdat, *dest, *dest0;
335 offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
336 dest0 = video_fb_address + offset;
338 switch (VIDEO_DATA_FORMAT) {
339 case GDF__8BIT_INDEX:
340 case GDF__8BIT_332RGB:
343 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
344 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
345 rows--; dest += VIDEO_LINE_LEN) {
349 (video_font_draw_table8[bits >> 4] &
352 if (VIDEO_FONT_WIDTH == 4)
356 (video_font_draw_table8[bits & 15] &
359 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
364 case GDF_15BIT_555RGB:
367 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
368 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
369 rows--; dest += VIDEO_LINE_LEN) {
373 SHORTSWAP32((video_font_draw_table15
374 [bits >> 6] & eorx) ^
377 SHORTSWAP32((video_font_draw_table15
378 [bits >> 4 & 3] & eorx) ^
381 if (VIDEO_FONT_WIDTH == 4)
385 SHORTSWAP32((video_font_draw_table15
386 [bits >> 2 & 3] & eorx) ^
389 SHORTSWAP32((video_font_draw_table15
393 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
398 case GDF_16BIT_565RGB:
401 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
402 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
403 rows--; dest += VIDEO_LINE_LEN) {
407 SHORTSWAP32((video_font_draw_table16
408 [bits >> 6] & eorx) ^
411 SHORTSWAP32((video_font_draw_table16
412 [bits >> 4 & 3] & eorx) ^
415 if (VIDEO_FONT_WIDTH == 4)
419 SHORTSWAP32((video_font_draw_table16
420 [bits >> 2 & 3] & eorx) ^
423 SHORTSWAP32((video_font_draw_table16
427 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
432 case GDF_32BIT_X888RGB:
435 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
436 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
437 rows--; dest += VIDEO_LINE_LEN) {
441 SWAP32((video_font_draw_table32
442 [bits >> 4][0] & eorx) ^ bgx);
444 SWAP32((video_font_draw_table32
445 [bits >> 4][1] & eorx) ^ bgx);
447 SWAP32((video_font_draw_table32
448 [bits >> 4][2] & eorx) ^ bgx);
450 SWAP32((video_font_draw_table32
451 [bits >> 4][3] & eorx) ^ bgx);
454 if (VIDEO_FONT_WIDTH == 4)
458 SWAP32((video_font_draw_table32
459 [bits & 15][0] & eorx) ^ bgx);
461 SWAP32((video_font_draw_table32
462 [bits & 15][1] & eorx) ^ bgx);
464 SWAP32((video_font_draw_table32
465 [bits & 15][2] & eorx) ^ bgx);
467 SWAP32((video_font_draw_table32
468 [bits & 15][3] & eorx) ^ bgx);
470 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
475 case GDF_24BIT_888RGB:
478 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
479 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
480 rows--; dest += VIDEO_LINE_LEN) {
484 (video_font_draw_table24[bits >> 4][0]
487 (video_font_draw_table24[bits >> 4][1]
490 (video_font_draw_table24[bits >> 4][2]
493 if (VIDEO_FONT_WIDTH == 4)
497 (video_font_draw_table24[bits & 15][0]
500 (video_font_draw_table24[bits & 15][1]
503 (video_font_draw_table24[bits & 15][2]
506 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
513 static inline void video_drawstring(int xx, int yy, unsigned char *s)
515 video_drawchars(xx, yy, s, strlen((char *) s));
518 static void video_putchar(int xx, int yy, unsigned char c)
520 video_drawchars(xx, yy + video_logo_height, &c, 1);
523 #if defined(CONFIG_VIDEO_SW_CURSOR)
524 static void video_set_cursor(void)
531 static void video_invertchar(int xx, int yy)
533 int firstx = xx * VIDEO_PIXEL_SIZE;
534 int lastx = (xx + VIDEO_FONT_WIDTH) * VIDEO_PIXEL_SIZE;
535 int firsty = yy * VIDEO_LINE_LEN;
536 int lasty = (yy + VIDEO_FONT_HEIGHT) * VIDEO_LINE_LEN;
538 for (y = firsty; y < lasty; y += VIDEO_LINE_LEN) {
539 for (x = firstx; x < lastx; x++) {
540 u8 *dest = (u8 *)(video_fb_address) + x + y;
546 void console_cursor(int state)
548 if (cursor_state != state) {
550 /* turn off the cursor */
551 video_invertchar(old_col * VIDEO_FONT_WIDTH,
552 old_row * VIDEO_FONT_HEIGHT +
555 /* turn off the cursor and record where it is */
556 video_invertchar(console_col * VIDEO_FONT_WIDTH,
557 console_row * VIDEO_FONT_HEIGHT +
559 old_col = console_col;
560 old_row = console_row;
562 cursor_state = state;
564 if (cfb_do_flush_cache)
565 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
569 #ifndef VIDEO_HW_RECTFILL
570 static void memsetl(int *p, int c, int v)
577 #ifndef VIDEO_HW_BITBLT
578 static void memcpyl(int *d, int *s, int c)
585 static void console_clear_line(int line, int begin, int end)
587 #ifdef VIDEO_HW_RECTFILL
588 video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
589 VIDEO_FONT_WIDTH * begin, /* dest pos x */
591 VIDEO_FONT_HEIGHT * line, /* dest pos y */
592 VIDEO_FONT_WIDTH * (end - begin + 1), /* fr. width */
593 VIDEO_FONT_HEIGHT, /* frame height */
597 if (begin == 0 && (end + 1) == CONSOLE_COLS) {
598 memsetl(CONSOLE_ROW_FIRST +
599 CONSOLE_ROW_SIZE * line, /* offset of row */
600 CONSOLE_ROW_SIZE >> 2, /* length of row */
607 offset = CONSOLE_ROW_FIRST +
608 CONSOLE_ROW_SIZE * line + /* offset of row */
610 VIDEO_PIXEL_SIZE * begin; /* offset of col */
611 size = VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE * (end - begin + 1);
612 size >>= 2; /* length to end for memsetl() */
613 /* fill at col offset of i'th line using bgx as fill color */
614 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
615 memsetl(offset + i * VIDEO_LINE_LEN, size, bgx);
620 static void console_scrollup(void)
622 const int rows = CONFIG_CONSOLE_SCROLL_LINES;
625 /* copy up rows ignoring the first one */
627 #ifdef VIDEO_HW_BITBLT
628 video_hw_bitblt(VIDEO_PIXEL_SIZE, /* bytes per pixel */
629 0, /* source pos x */
631 VIDEO_FONT_HEIGHT * rows, /* source pos y */
633 video_logo_height, /* dest pos y */
634 VIDEO_VISIBLE_COLS, /* frame width */
637 - VIDEO_FONT_HEIGHT * rows /* frame height */
640 memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_FIRST + rows * CONSOLE_ROW_SIZE,
641 (CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows) >> 2);
643 /* clear the last one */
644 for (i = 1; i <= rows; i++)
645 console_clear_line(CONSOLE_ROWS - i, 0, CONSOLE_COLS - 1);
647 /* Decrement row number */
651 static void console_back(void)
655 if (console_col < 0) {
656 console_col = CONSOLE_COLS - 1;
663 #ifdef CONFIG_CFB_CONSOLE_ANSI
665 static void console_clear(void)
667 #ifdef VIDEO_HW_RECTFILL
668 video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
670 video_logo_height, /* dest pos y */
671 VIDEO_VISIBLE_COLS, /* frame width */
672 VIDEO_VISIBLE_ROWS, /* frame height */
676 memsetl(CONSOLE_ROW_FIRST, CONSOLE_SIZE, bgx);
680 static void console_cursor_fix(void)
684 if (console_row >= CONSOLE_ROWS)
685 console_row = CONSOLE_ROWS - 1;
688 if (console_col >= CONSOLE_COLS)
689 console_col = CONSOLE_COLS - 1;
692 static void console_cursor_up(int n)
695 console_cursor_fix();
698 static void console_cursor_down(int n)
701 console_cursor_fix();
704 static void console_cursor_left(int n)
707 console_cursor_fix();
710 static void console_cursor_right(int n)
713 console_cursor_fix();
716 static void console_cursor_set_position(int row, int col)
718 if (console_row != -1)
720 if (console_col != -1)
722 console_cursor_fix();
725 static void console_previousline(int n)
727 /* FIXME: also scroll terminal ? */
729 console_cursor_fix();
732 static void console_swap_colors(void)
740 static inline int console_cursor_is_visible(void)
742 return !ansi_cursor_hidden;
745 static inline int console_cursor_is_visible(void)
751 static void console_newline(int n)
756 /* Check if we need to scroll the terminal */
757 if (console_row >= CONSOLE_ROWS) {
758 /* Scroll everything up */
763 static void console_cr(void)
768 static void parse_putc(const char c)
772 if (console_cursor_is_visible())
776 case 13: /* back to first column */
780 case '\n': /* next line */
781 if (console_col || (!console_col && nl))
787 console_col |= 0x0008;
788 console_col &= ~0x0007;
790 if (console_col >= CONSOLE_COLS)
794 case 8: /* backspace */
801 default: /* draw the char */
802 video_putchar(console_col * VIDEO_FONT_WIDTH,
803 console_row * VIDEO_FONT_HEIGHT, c);
806 /* check for newline */
807 if (console_col >= CONSOLE_COLS) {
813 if (console_cursor_is_visible())
817 static void cfb_video_putc(struct stdio_dev *dev, const char c)
819 #ifdef CONFIG_CFB_CONSOLE_ANSI
823 for (i = 0; i < ansi_buf_size; ++i)
824 parse_putc(ansi_buf[i]);
830 if (ansi_buf_size > 0) {
850 ansi_buf[ansi_buf_size++] = c;
852 if (ansi_buf_size >= sizeof(ansi_buf))
855 for (i = 0; i < ansi_buf_size; ++i) {
861 if (ansi_buf[i] == 27)
868 if (ansi_buf[i] == '[')
875 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
876 num1 = ansi_buf[i]-'0';
878 } else if (ansi_buf[i] != '?') {
886 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
888 num1 += ansi_buf[i]-'0';
896 if (ansi_buf[i] != ';') {
904 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
905 num2 = ansi_buf[i]-'0';
912 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
914 num2 += ansi_buf[i]-'0';
922 if ((ansi_buf[i] >= 'A' && ansi_buf[i] <= 'H')
923 || ansi_buf[i] == 'J'
924 || ansi_buf[i] == 'K'
925 || ansi_buf[i] == 'h'
926 || ansi_buf[i] == 'l'
927 || ansi_buf[i] == 'm') {
937 for (i = 0; i < ansi_buf_size; ++i)
938 parse_putc(ansi_buf[i]);
944 if (!ansi_cursor_hidden)
949 /* move cursor num1 rows up */
950 console_cursor_up(num1);
953 /* move cursor num1 rows down */
954 console_cursor_down(num1);
957 /* move cursor num1 columns forward */
958 console_cursor_right(num1);
961 /* move cursor num1 columns back */
962 console_cursor_left(num1);
965 /* move cursor num1 rows up at begin of row */
966 console_previousline(num1);
969 /* move cursor num1 rows down at begin of row */
970 console_newline(num1);
973 /* move cursor to column num1 */
974 console_cursor_set_position(-1, num1-1);
977 /* move cursor to row num1, column num2 */
978 console_cursor_set_position(num1-1, num2-1);
981 /* clear console and move cursor to 0, 0 */
983 console_cursor_set_position(0, 0);
988 console_clear_line(console_row,
992 console_clear_line(console_row,
995 console_clear_line(console_row,
999 ansi_cursor_hidden = 0;
1002 ansi_cursor_hidden = 1;
1005 if (num1 == 0) { /* reset swapped colors */
1006 if (ansi_colors_need_revert) {
1007 console_swap_colors();
1008 ansi_colors_need_revert = 0;
1010 } else if (num1 == 7) { /* once swap colors */
1011 if (!ansi_colors_need_revert) {
1012 console_swap_colors();
1013 ansi_colors_need_revert = 1;
1018 if (!ansi_cursor_hidden)
1027 if (cfb_do_flush_cache)
1028 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
1031 static void cfb_video_puts(struct stdio_dev *dev, const char *s)
1033 int flush = cfb_do_flush_cache;
1034 int count = strlen(s);
1036 /* temporarily disable cache flush */
1037 cfb_do_flush_cache = 0;
1040 cfb_video_putc(dev, *s++);
1043 cfb_do_flush_cache = flush;
1044 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
1049 * Do not enforce drivers (or board code) to provide empty
1050 * video_set_lut() if they do not support 8 bpp format.
1051 * Implement weak default function instead.
1053 __weak void video_set_lut(unsigned int index, unsigned char r,
1054 unsigned char g, unsigned char b)
1058 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
1060 #define FILL_8BIT_332RGB(r,g,b) { \
1061 *fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \
1065 #define FILL_15BIT_555RGB(r,g,b) { \
1066 *(unsigned short *)fb = \
1067 SWAP16((unsigned short)(((r>>3)<<10) | \
1073 #define FILL_16BIT_565RGB(r,g,b) { \
1074 *(unsigned short *)fb = \
1075 SWAP16((unsigned short)((((r)>>3)<<11)| \
1081 #define FILL_32BIT_X888RGB(r,g,b) { \
1082 *(unsigned long *)fb = \
1083 SWAP32((unsigned long)(((r<<16) | \
1089 #ifdef VIDEO_FB_LITTLE_ENDIAN
1090 #define FILL_24BIT_888RGB(r,g,b) { \
1097 #define FILL_24BIT_888RGB(r,g,b) { \
1105 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1106 static inline void fill_555rgb_pswap(uchar *fb, int x, u8 r, u8 g, u8 b)
1108 ushort *dst = (ushort *) fb;
1109 ushort color = (ushort) (((r >> 3) << 10) |
1120 * RLE8 bitmap support
1123 #ifdef CONFIG_VIDEO_BMP_RLE8
1124 /* Pre-calculated color table entry */
1127 unsigned short w; /* word */
1128 unsigned int dw; /* double word */
1129 } ce; /* color entry */
1133 * Helper to draw encoded/unencoded run.
1135 static void draw_bitmap(uchar **fb, uchar *bm, struct palette *p,
1138 ulong addr = (ulong) *fb;
1144 * Setup offset of the color index in the bitmap.
1145 * Color index of encoded run is at offset 1.
1147 off = enc ? &enc_off : &i;
1149 switch (VIDEO_DATA_FORMAT) {
1150 case GDF__8BIT_INDEX:
1151 for (i = 0; i < cnt; i++)
1152 *(unsigned char *) addr++ = bm[*off];
1154 case GDF_15BIT_555RGB:
1155 case GDF_16BIT_565RGB:
1156 /* differences handled while pre-calculating palette */
1157 for (i = 0; i < cnt; i++) {
1158 *(unsigned short *) addr = p[bm[*off]].ce.w;
1162 case GDF_32BIT_X888RGB:
1163 for (i = 0; i < cnt; i++) {
1164 *(unsigned long *) addr = p[bm[*off]].ce.dw;
1169 *fb = (uchar *) addr; /* return modified address */
1172 static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff,
1173 int width, int height)
1177 unsigned int cnt, runlen;
1179 int x, y, bpp, i, ncolors;
1180 struct palette p[256];
1181 struct bmp_color_table_entry cte;
1182 int green_shift, red_off;
1183 int limit = (VIDEO_LINE_LEN / VIDEO_PIXEL_SIZE) * VIDEO_ROWS;
1187 y = __le32_to_cpu(img->header.height) - 1;
1188 ncolors = __le32_to_cpu(img->header.colors_used);
1189 bpp = VIDEO_PIXEL_SIZE;
1190 fbp = (unsigned char *) ((unsigned int) video_fb_address +
1191 (y + yoff) * VIDEO_LINE_LEN +
1194 bm = (uchar *) img + __le32_to_cpu(img->header.data_offset);
1196 /* pre-calculate and setup palette */
1197 switch (VIDEO_DATA_FORMAT) {
1198 case GDF__8BIT_INDEX:
1199 for (i = 0; i < ncolors; i++) {
1200 cte = img->color_table[i];
1201 video_set_lut(i, cte.red, cte.green, cte.blue);
1204 case GDF_15BIT_555RGB:
1205 case GDF_16BIT_565RGB:
1206 if (VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) {
1213 for (i = 0; i < ncolors; i++) {
1214 cte = img->color_table[i];
1215 p[i].ce.w = SWAP16((unsigned short)
1216 (((cte.red >> 3) << red_off) |
1217 ((cte.green >> green_shift) << 5) |
1221 case GDF_32BIT_X888RGB:
1222 for (i = 0; i < ncolors; i++) {
1223 cte = img->color_table[i];
1224 p[i].ce.dw = SWAP32((cte.red << 16) |
1230 printf("RLE Bitmap unsupported in video mode 0x%x\n",
1240 /* scan line end marker */
1244 fbp = (unsigned char *)
1245 ((unsigned int) video_fb_address +
1246 (y + yoff) * VIDEO_LINE_LEN +
1250 /* end of bitmap data marker */
1254 /* run offset marker */
1257 fbp = (unsigned char *)
1258 ((unsigned int) video_fb_address +
1259 (y + yoff) * VIDEO_LINE_LEN +
1277 if (x + runlen > width)
1279 draw_bitmap(&fbp, bm, p, cnt, 0);
1285 bm++; /* 0 padding if length is odd */
1296 if (y < height) { /* only draw into visible area */
1302 if (x + runlen > width)
1304 draw_bitmap(&fbp, bm, p, cnt, 1);
1313 printf("Error: Too much encoded pixel data, validate your bitmap\n");
1319 * Display the BMP file located at address bmp_image.
1321 int video_display_bitmap(ulong bmp_image, int x, int y)
1323 ushort xcount, ycount;
1325 struct bmp_image *bmp = (struct bmp_image *)bmp_image;
1328 unsigned long width, height, bpp;
1330 unsigned long compression;
1331 struct bmp_color_table_entry cte;
1333 #ifdef CONFIG_VIDEO_BMP_GZIP
1334 unsigned char *dst = NULL;
1340 if (!((bmp->header.signature[0] == 'B') &&
1341 (bmp->header.signature[1] == 'M'))) {
1343 #ifdef CONFIG_VIDEO_BMP_GZIP
1345 * Could be a gzipped bmp image, try to decrompress...
1347 len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
1348 dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
1350 printf("Error: malloc in gunzip failed!\n");
1354 * NB: we need to force offset of +2
1355 * See doc/README.displaying-bmps
1357 if (gunzip(dst+2, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE-2,
1358 (uchar *) bmp_image,
1360 printf("Error: no valid bmp or bmp.gz image at %lx\n",
1365 if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
1366 printf("Image could be truncated "
1367 "(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
1371 * Set addr to decompressed image
1373 bmp = (struct bmp_image *)(dst+2);
1375 if (!((bmp->header.signature[0] == 'B') &&
1376 (bmp->header.signature[1] == 'M'))) {
1377 printf("Error: no valid bmp.gz image at %lx\n",
1383 printf("Error: no valid bmp image at %lx\n", bmp_image);
1385 #endif /* CONFIG_VIDEO_BMP_GZIP */
1388 width = le32_to_cpu(bmp->header.width);
1389 height = le32_to_cpu(bmp->header.height);
1390 bpp = le16_to_cpu(bmp->header.bit_count);
1391 colors = le32_to_cpu(bmp->header.colors_used);
1392 compression = le32_to_cpu(bmp->header.compression);
1394 debug("Display-bmp: %ld x %ld with %d colors\n",
1395 width, height, colors);
1397 if (compression != BMP_BI_RGB
1398 #ifdef CONFIG_VIDEO_BMP_RLE8
1399 && compression != BMP_BI_RLE8
1402 printf("Error: compression type %ld not supported\n",
1404 #ifdef CONFIG_VIDEO_BMP_GZIP
1411 padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
1413 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
1414 if (x == BMP_ALIGN_CENTER)
1415 x = max(0, (int)(VIDEO_VISIBLE_COLS - width) / 2);
1417 x = max(0, (int)(VIDEO_VISIBLE_COLS - width + x + 1));
1419 if (y == BMP_ALIGN_CENTER)
1420 y = max(0, (int)(VIDEO_VISIBLE_ROWS - height) / 2);
1422 y = max(0, (int)(VIDEO_VISIBLE_ROWS - height + y + 1));
1423 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
1426 * Just ignore elements which are completely beyond screen
1429 if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS))
1432 if ((x + width) > VIDEO_VISIBLE_COLS)
1433 width = VIDEO_VISIBLE_COLS - x;
1434 if ((y + height) > VIDEO_VISIBLE_ROWS)
1435 height = VIDEO_VISIBLE_ROWS - y;
1437 bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
1438 fb = (uchar *) (video_fb_address +
1439 ((y + height - 1) * VIDEO_LINE_LEN) +
1440 x * VIDEO_PIXEL_SIZE);
1442 #ifdef CONFIG_VIDEO_BMP_RLE8
1443 if (compression == BMP_BI_RLE8) {
1444 return display_rle8_bitmap(bmp, x, y, width, height);
1448 /* We handle only 4, 8, or 24 bpp bitmaps */
1449 switch (le16_to_cpu(bmp->header.bit_count)) {
1451 padded_line -= width / 2;
1454 switch (VIDEO_DATA_FORMAT) {
1455 case GDF_32BIT_X888RGB:
1459 * Don't assume that 'width' is an
1462 for (xcount = 0; xcount < width; xcount++) {
1470 cte = bmp->color_table[idx];
1471 FILL_32BIT_X888RGB(cte.red, cte.green,
1474 bmap += padded_line;
1475 fb -= VIDEO_LINE_LEN + width *
1480 puts("4bpp bitmap unsupported with current "
1487 padded_line -= width;
1488 if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
1490 for (xcount = 0; xcount < colors; ++xcount) {
1491 cte = bmp->color_table[xcount];
1492 video_set_lut(xcount, cte.red, cte.green,
1497 switch (VIDEO_DATA_FORMAT) {
1498 case GDF__8BIT_INDEX:
1505 bmap += padded_line;
1506 fb -= VIDEO_LINE_LEN + width *
1510 case GDF__8BIT_332RGB:
1515 cte = bmp->color_table[*bmap++];
1516 FILL_8BIT_332RGB(cte.red, cte.green,
1519 bmap += padded_line;
1520 fb -= VIDEO_LINE_LEN + width *
1524 case GDF_15BIT_555RGB:
1526 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1532 cte = bmp->color_table[*bmap++];
1533 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1534 fill_555rgb_pswap(fb, xpos++, cte.red,
1539 FILL_15BIT_555RGB(cte.red, cte.green,
1543 bmap += padded_line;
1544 fb -= VIDEO_LINE_LEN + width *
1548 case GDF_16BIT_565RGB:
1553 cte = bmp->color_table[*bmap++];
1554 FILL_16BIT_565RGB(cte.red, cte.green,
1557 bmap += padded_line;
1558 fb -= VIDEO_LINE_LEN + width *
1562 case GDF_32BIT_X888RGB:
1567 cte = bmp->color_table[*bmap++];
1568 FILL_32BIT_X888RGB(cte.red, cte.green,
1571 bmap += padded_line;
1572 fb -= VIDEO_LINE_LEN + width *
1576 case GDF_24BIT_888RGB:
1581 cte = bmp->color_table[*bmap++];
1582 FILL_24BIT_888RGB(cte.red, cte.green,
1585 bmap += padded_line;
1586 fb -= VIDEO_LINE_LEN + width *
1593 padded_line -= 3 * width;
1595 switch (VIDEO_DATA_FORMAT) {
1596 case GDF__8BIT_332RGB:
1601 FILL_8BIT_332RGB(bmap[2], bmap[1],
1605 bmap += padded_line;
1606 fb -= VIDEO_LINE_LEN + width *
1610 case GDF_15BIT_555RGB:
1612 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1618 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1619 fill_555rgb_pswap(fb, xpos++, bmap[2],
1623 FILL_15BIT_555RGB(bmap[2], bmap[1],
1628 bmap += padded_line;
1629 fb -= VIDEO_LINE_LEN + width *
1633 case GDF_16BIT_565RGB:
1638 FILL_16BIT_565RGB(bmap[2], bmap[1],
1642 bmap += padded_line;
1643 fb -= VIDEO_LINE_LEN + width *
1647 case GDF_32BIT_X888RGB:
1652 FILL_32BIT_X888RGB(bmap[2], bmap[1],
1656 bmap += padded_line;
1657 fb -= VIDEO_LINE_LEN + width *
1661 case GDF_24BIT_888RGB:
1666 FILL_24BIT_888RGB(bmap[2], bmap[1],
1670 bmap += padded_line;
1671 fb -= VIDEO_LINE_LEN + width *
1676 printf("Error: 24 bits/pixel bitmap incompatible "
1677 "with current video mode\n");
1682 printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
1683 le16_to_cpu(bmp->header.bit_count));
1687 #ifdef CONFIG_VIDEO_BMP_GZIP
1693 if (cfb_do_flush_cache)
1694 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
1700 #ifdef CONFIG_VIDEO_LOGO
1701 static int video_logo_xpos;
1702 static int video_logo_ypos;
1704 static void plot_logo_or_black(void *screen, int x, int y, int black);
1706 static void logo_plot(void *screen, int x, int y)
1708 plot_logo_or_black(screen, x, y, 0);
1711 static void logo_black(void)
1713 plot_logo_or_black(video_fb_address, video_logo_xpos, video_logo_ypos,
1717 static int do_clrlogo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1720 return cmd_usage(cmdtp);
1727 clrlogo, 1, 0, do_clrlogo,
1728 "fill the boot logo area with black",
1732 static void plot_logo_or_black(void *screen, int x, int y, int black)
1736 int skip = VIDEO_LINE_LEN - VIDEO_LOGO_WIDTH * VIDEO_PIXEL_SIZE;
1737 int ycount = video_logo_height;
1738 unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
1739 unsigned char *source;
1740 unsigned char *dest;
1742 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
1743 if (x == BMP_ALIGN_CENTER)
1744 x = max(0, (int)(VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH) / 2);
1746 x = max(0, (int)(VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH + x + 1));
1748 if (y == BMP_ALIGN_CENTER)
1749 y = max(0, (int)(VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT) / 2);
1751 y = max(0, (int)(VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1));
1752 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
1754 dest = (unsigned char *)screen + y * VIDEO_LINE_LEN + x * VIDEO_PIXEL_SIZE;
1756 #ifdef CONFIG_VIDEO_BMP_LOGO
1757 source = bmp_logo_bitmap;
1759 /* Allocate temporary space for computing colormap */
1760 logo_red = malloc(BMP_LOGO_COLORS);
1761 logo_green = malloc(BMP_LOGO_COLORS);
1762 logo_blue = malloc(BMP_LOGO_COLORS);
1763 /* Compute color map */
1764 for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
1765 logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4;
1766 logo_green[i] = (bmp_logo_palette[i] & 0x00f0);
1767 logo_blue[i] = (bmp_logo_palette[i] & 0x000f) << 4;
1770 source = linux_logo;
1771 logo_red = linux_logo_red;
1772 logo_green = linux_logo_green;
1773 logo_blue = linux_logo_blue;
1776 if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
1777 for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
1778 video_set_lut(i + VIDEO_LOGO_LUT_OFFSET,
1779 logo_red[i], logo_green[i],
1785 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1788 xcount = VIDEO_LOGO_WIDTH;
1795 r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
1796 g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
1797 b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
1800 switch (VIDEO_DATA_FORMAT) {
1801 case GDF__8BIT_INDEX:
1804 case GDF__8BIT_332RGB:
1805 *dest = ((r >> 5) << 5) |
1809 case GDF_15BIT_555RGB:
1810 #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1811 fill_555rgb_pswap(dest, xpos++, r, g, b);
1813 *(unsigned short *) dest =
1814 SWAP16((unsigned short) (
1820 case GDF_16BIT_565RGB:
1821 *(unsigned short *) dest =
1822 SWAP16((unsigned short) (
1827 case GDF_32BIT_X888RGB:
1828 *(unsigned long *) dest =
1829 SWAP32((unsigned long) (
1834 case GDF_24BIT_888RGB:
1835 #ifdef VIDEO_FB_LITTLE_ENDIAN
1847 dest += VIDEO_PIXEL_SIZE;
1851 #ifdef CONFIG_VIDEO_BMP_LOGO
1858 static void *video_logo(void)
1861 __maybe_unused int y_off = 0;
1862 __maybe_unused ulong addr;
1863 __maybe_unused char *s;
1864 __maybe_unused int len, space;
1866 splash_get_pos(&video_logo_xpos, &video_logo_ypos);
1868 #ifdef CONFIG_SPLASH_SCREEN
1869 s = getenv("splashimage");
1871 splash_screen_prepare();
1872 addr = simple_strtoul(s, NULL, 16);
1874 if (video_display_bitmap(addr,
1876 video_logo_ypos) == 0) {
1877 video_logo_height = 0;
1878 return ((void *) (video_fb_address));
1881 #endif /* CONFIG_SPLASH_SCREEN */
1883 logo_plot(video_fb_address, video_logo_xpos, video_logo_ypos);
1885 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
1887 * when using splashpos for video_logo, skip any info
1888 * output on video console if the logo is not at 0,0
1890 if (video_logo_xpos || video_logo_ypos) {
1892 * video_logo_height is used in text and cursor offset
1893 * calculations. Since the console is below the logo,
1894 * we need to adjust the logo height
1896 if (video_logo_ypos == BMP_ALIGN_CENTER)
1897 video_logo_height += max(0, (int)(VIDEO_VISIBLE_ROWS -
1898 VIDEO_LOGO_HEIGHT) / 2);
1899 else if (video_logo_ypos > 0)
1900 video_logo_height += video_logo_ypos;
1902 return video_fb_address + video_logo_height * VIDEO_LINE_LEN;
1905 if (board_cfb_skip())
1908 sprintf(info, " %s", version_string);
1910 #ifndef CONFIG_HIDE_LOGO_VERSION
1911 space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
1915 video_drawchars(VIDEO_INFO_X, VIDEO_INFO_Y,
1916 (uchar *) info, space);
1917 video_drawchars(VIDEO_INFO_X + VIDEO_FONT_WIDTH,
1918 VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
1919 (uchar *) info + space, len - space);
1922 video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);
1924 #ifdef CONFIG_CONSOLE_EXTRA_INFO
1927 ((video_logo_height -
1928 VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
1930 for (i = 1; i < n; i++) {
1931 video_get_info_str(i, info);
1937 video_drawchars(VIDEO_INFO_X,
1941 (uchar *) info, space);
1943 video_drawchars(VIDEO_INFO_X +
1948 (uchar *) info + space,
1951 video_drawstring(VIDEO_INFO_X,
1962 return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
1966 static int cfb_fb_is_in_dram(void)
1969 #if defined(CONFIG_ARM) || defined(CONFIG_AVR32) || defined(COFNIG_NDS32) || \
1970 defined(CONFIG_SANDBOX) || defined(CONFIG_X86)
1974 for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
1975 start = bd->bi_dram[i].start;
1976 end = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
1977 if ((ulong)video_fb_address >= start &&
1978 (ulong)video_fb_address < end)
1982 if ((ulong)video_fb_address >= bd->bi_memstart &&
1983 (ulong)video_fb_address < bd->bi_memstart + bd->bi_memsize)
1989 void video_clear(void)
1991 if (!video_fb_address)
1993 #ifdef VIDEO_HW_RECTFILL
1994 video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
1997 VIDEO_VISIBLE_COLS, /* frame width */
1998 VIDEO_VISIBLE_ROWS, /* frame height */
1999 bgx /* fill color */
2002 memsetl(video_fb_address,
2003 (VIDEO_VISIBLE_ROWS * VIDEO_LINE_LEN) / sizeof(int), bgx);
2007 static int cfg_video_init(void)
2009 unsigned char color8;
2011 pGD = video_hw_init();
2015 video_fb_address = (void *) VIDEO_FB_ADRS;
2017 cfb_do_flush_cache = cfb_fb_is_in_dram() && dcache_status();
2019 /* Init drawing pats */
2020 switch (VIDEO_DATA_FORMAT) {
2021 case GDF__8BIT_INDEX:
2022 video_set_lut(0x01, CONFIG_SYS_CONSOLE_FG_COL,
2023 CONFIG_SYS_CONSOLE_FG_COL,
2024 CONFIG_SYS_CONSOLE_FG_COL);
2025 video_set_lut(0x00, CONFIG_SYS_CONSOLE_BG_COL,
2026 CONFIG_SYS_CONSOLE_BG_COL,
2027 CONFIG_SYS_CONSOLE_BG_COL);
2031 case GDF__8BIT_332RGB:
2032 color8 = ((CONFIG_SYS_CONSOLE_FG_COL & 0xe0) |
2033 ((CONFIG_SYS_CONSOLE_FG_COL >> 3) & 0x1c) |
2034 CONFIG_SYS_CONSOLE_FG_COL >> 6);
2035 fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
2037 color8 = ((CONFIG_SYS_CONSOLE_BG_COL & 0xe0) |
2038 ((CONFIG_SYS_CONSOLE_BG_COL >> 3) & 0x1c) |
2039 CONFIG_SYS_CONSOLE_BG_COL >> 6);
2040 bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
2043 case GDF_15BIT_555RGB:
2044 fgx = (((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 26) |
2045 ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 21) |
2046 ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 16) |
2047 ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 10) |
2048 ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 5) |
2049 (CONFIG_SYS_CONSOLE_FG_COL >> 3));
2050 bgx = (((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 26) |
2051 ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 21) |
2052 ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 16) |
2053 ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 10) |
2054 ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 5) |
2055 (CONFIG_SYS_CONSOLE_BG_COL >> 3));
2057 case GDF_16BIT_565RGB:
2058 fgx = (((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 27) |
2059 ((CONFIG_SYS_CONSOLE_FG_COL >> 2) << 21) |
2060 ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 16) |
2061 ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 11) |
2062 ((CONFIG_SYS_CONSOLE_FG_COL >> 2) << 5) |
2063 (CONFIG_SYS_CONSOLE_FG_COL >> 3));
2064 bgx = (((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 27) |
2065 ((CONFIG_SYS_CONSOLE_BG_COL >> 2) << 21) |
2066 ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 16) |
2067 ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 11) |
2068 ((CONFIG_SYS_CONSOLE_BG_COL >> 2) << 5) |
2069 (CONFIG_SYS_CONSOLE_BG_COL >> 3));
2071 case GDF_32BIT_X888RGB:
2072 fgx = (CONFIG_SYS_CONSOLE_FG_COL << 16) |
2073 (CONFIG_SYS_CONSOLE_FG_COL << 8) |
2074 CONFIG_SYS_CONSOLE_FG_COL;
2075 bgx = (CONFIG_SYS_CONSOLE_BG_COL << 16) |
2076 (CONFIG_SYS_CONSOLE_BG_COL << 8) |
2077 CONFIG_SYS_CONSOLE_BG_COL;
2079 case GDF_24BIT_888RGB:
2080 fgx = (CONFIG_SYS_CONSOLE_FG_COL << 24) |
2081 (CONFIG_SYS_CONSOLE_FG_COL << 16) |
2082 (CONFIG_SYS_CONSOLE_FG_COL << 8) |
2083 CONFIG_SYS_CONSOLE_FG_COL;
2084 bgx = (CONFIG_SYS_CONSOLE_BG_COL << 24) |
2085 (CONFIG_SYS_CONSOLE_BG_COL << 16) |
2086 (CONFIG_SYS_CONSOLE_BG_COL << 8) |
2087 CONFIG_SYS_CONSOLE_BG_COL;
2094 #ifdef CONFIG_VIDEO_LOGO
2095 /* Plot the logo and get start point of console */
2096 debug("Video: Drawing the logo ...\n");
2097 video_console_address = video_logo();
2099 video_console_address = video_fb_address;
2102 /* Initialize the console */
2106 if (cfb_do_flush_cache)
2107 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
2113 * Implement a weak default function for boards that optionally
2114 * need to skip the video initialization.
2116 __weak int board_video_skip(void)
2118 /* As default, don't skip test */
2122 int drv_video_init(void)
2124 struct stdio_dev console_dev;
2126 bool __maybe_unused keyboard_ok = false;
2128 /* Check if video initialization should be skipped */
2129 if (board_video_skip())
2132 /* Init video chip - returns with framebuffer cleared */
2133 if (cfg_video_init() == -1)
2136 if (board_cfb_skip())
2139 #if defined(CONFIG_VGA_AS_SINGLE_DEVICE)
2140 have_keyboard = false;
2141 #elif defined(CONFIG_OF_CONTROL)
2142 have_keyboard = !fdtdec_get_config_bool(gd->fdt_blob,
2143 "u-boot,no-keyboard");
2145 have_keyboard = true;
2147 if (have_keyboard) {
2148 debug("KBD: Keyboard init ...\n");
2149 #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
2150 keyboard_ok = !(VIDEO_KBD_INIT_FCT == -1);
2154 /* Init vga device */
2155 memset(&console_dev, 0, sizeof(console_dev));
2156 strcpy(console_dev.name, "vga");
2157 console_dev.flags = DEV_FLAGS_OUTPUT;
2158 console_dev.putc = cfb_video_putc; /* 'putc' function */
2159 console_dev.puts = cfb_video_puts; /* 'puts' function */
2161 #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
2162 if (have_keyboard && keyboard_ok) {
2163 /* Also init console device */
2164 console_dev.flags |= DEV_FLAGS_INPUT;
2165 console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */
2166 console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */
2170 if (stdio_register(&console_dev) != 0)
2173 /* Return success */
2177 void video_position_cursor(unsigned col, unsigned row)
2179 console_col = min(col, CONSOLE_COLS - 1);
2180 console_row = min(row, CONSOLE_ROWS - 1);
2183 int video_get_pixel_width(void)
2185 return VIDEO_VISIBLE_COLS;
2188 int video_get_pixel_height(void)
2190 return VIDEO_VISIBLE_ROWS;
2193 int video_get_screen_rows(void)
2195 return CONSOLE_ROWS;
2198 int video_get_screen_columns(void)
2200 return CONSOLE_COLS;