1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68#include <common.h>
69#include <fdtdec.h>
70#include <version.h>
71#include <malloc.h>
72#include <video.h>
73#include <linux/compiler.h>
74
75
76
77
78#ifdef CONFIG_VIDEO_CT69000
79
80#define VIDEO_FB_LITTLE_ENDIAN
81#define VIDEO_HW_RECTFILL
82#define VIDEO_HW_BITBLT
83#endif
84
85#if defined(CONFIG_VIDEO_MXS)
86#define VIDEO_FB_16BPP_WORD_SWAP
87#endif
88
89
90
91
92#ifdef CONFIG_VIDEO_MB862xx
93
94#ifdef CONFIG_VIDEO_CORALP
95#define VIDEO_FB_LITTLE_ENDIAN
96#endif
97#ifdef CONFIG_VIDEO_MB862xx_ACCEL
98#define VIDEO_HW_RECTFILL
99#define VIDEO_HW_BITBLT
100#endif
101#endif
102
103
104
105
106#if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_IPUV3)
107#define VIDEO_FB_16BPP_WORD_SWAP
108#endif
109
110
111
112
113#include <video_fb.h>
114
115#include <splash.h>
116
117
118
119
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)
125
126
127
128
129
130#include <version.h>
131#include <linux/types.h>
132#include <stdio_dev.h>
133#include <video_font.h>
134
135#if defined(CONFIG_CMD_DATE)
136#include <rtc.h>
137#endif
138
139#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
140#include <watchdog.h>
141#include <bmp_layout.h>
142#include <splash.h>
143#endif
144
145#if !defined(CONFIG_VIDEO_SW_CURSOR)
146
147#define CURSOR_ON
148#define CURSOR_OFF
149#define CURSOR_SET
150#endif
151
152#if defined(CONFIG_VIDEO_SW_CURSOR)
153void console_cursor(int state);
154
155#define CURSOR_ON console_cursor(1)
156#define CURSOR_OFF console_cursor(0)
157#define CURSOR_SET video_set_cursor()
158#endif
159
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
168
169#else
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
174#define __initdata
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
181#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
182#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
183#else
184#define VIDEO_LOGO_WIDTH 0
185#define VIDEO_LOGO_HEIGHT 0
186#endif
187
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)
192#endif
193#define VIDEO_SIZE (VIDEO_ROWS * VIDEO_LINE_LEN)
194#define VIDEO_BURST_LEN (VIDEO_COLS/8)
195
196#ifdef CONFIG_VIDEO_LOGO
197#define CONSOLE_ROWS ((VIDEO_ROWS - video_logo_height) / VIDEO_FONT_HEIGHT)
198#else
199#define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
200#endif
201
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)
208
209
210#ifndef CONFIG_CONSOLE_SCROLL_LINES
211#define CONFIG_CONSOLE_SCROLL_LINES 1
212#endif
213
214
215#ifdef VIDEO_FB_LITTLE_ENDIAN
216#define SWAP16(x) ((((x) & 0x00ff) << 8) | \
217 ((x) >> 8) \
218 )
219#define SWAP32(x) ((((x) & 0x000000ff) << 24) | \
220 (((x) & 0x0000ff00) << 8) | \
221 (((x) & 0x00ff0000) >> 8) | \
222 (((x) & 0xff000000) >> 24) \
223 )
224#define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | \
225 (((x) & 0x0000ff00) >> 8) | \
226 (((x) & 0x00ff0000) << 8) | \
227 (((x) & 0xff000000) >> 8) \
228 )
229#else
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))
234#else
235#define SHORTSWAP32(x) (x)
236#endif
237#endif
238
239DECLARE_GLOBAL_DATA_PTR;
240
241
242static GraphicDevice *pGD;
243
244static void *video_fb_address;
245static void *video_console_address;
246
247static int video_logo_height = VIDEO_LOGO_HEIGHT;
248
249static int __maybe_unused cursor_state;
250static int __maybe_unused old_col;
251static int __maybe_unused old_row;
252
253static int console_col;
254static int console_row;
255
256static u32 eorx, fgx, bgx;
257
258static int cfb_do_flush_cache;
259
260#ifdef CONFIG_CFB_CONSOLE_ANSI
261static char ansi_buf[10];
262static int ansi_buf_size;
263static int ansi_colors_need_revert;
264static int ansi_cursor_hidden;
265#endif
266
267static 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
272};
273
274static const int video_font_draw_table15[] = {
275 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff
276};
277
278static const int video_font_draw_table16[] = {
279 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
280};
281
282static 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}
299};
300
301static 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}
318};
319
320
321
322
323
324__weak int board_cfb_skip(void)
325{
326
327 return 0;
328}
329
330static void video_drawchars(int xx, int yy, unsigned char *s, int count)
331{
332 u8 *cdat, *dest, *dest0;
333 int rows, offset, c;
334
335 offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
336 dest0 = video_fb_address + offset;
337
338 switch (VIDEO_DATA_FORMAT) {
339 case GDF__8BIT_INDEX:
340 case GDF__8BIT_332RGB:
341 while (count--) {
342 c = *s;
343 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
344 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
345 rows--; dest += VIDEO_LINE_LEN) {
346 u8 bits = *cdat++;
347
348 ((u32 *) dest)[0] =
349 (video_font_draw_table8[bits >> 4] &
350 eorx) ^ bgx;
351
352 if (VIDEO_FONT_WIDTH == 4)
353 continue;
354
355 ((u32 *) dest)[1] =
356 (video_font_draw_table8[bits & 15] &
357 eorx) ^ bgx;
358 }
359 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
360 s++;
361 }
362 break;
363
364 case GDF_15BIT_555RGB:
365 while (count--) {
366 c = *s;
367 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
368 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
369 rows--; dest += VIDEO_LINE_LEN) {
370 u8 bits = *cdat++;
371
372 ((u32 *) dest)[0] =
373 SHORTSWAP32((video_font_draw_table15
374 [bits >> 6] & eorx) ^
375 bgx);
376 ((u32 *) dest)[1] =
377 SHORTSWAP32((video_font_draw_table15
378 [bits >> 4 & 3] & eorx) ^
379 bgx);
380
381 if (VIDEO_FONT_WIDTH == 4)
382 continue;
383
384 ((u32 *) dest)[2] =
385 SHORTSWAP32((video_font_draw_table15
386 [bits >> 2 & 3] & eorx) ^
387 bgx);
388 ((u32 *) dest)[3] =
389 SHORTSWAP32((video_font_draw_table15
390 [bits & 3] & eorx) ^
391 bgx);
392 }
393 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
394 s++;
395 }
396 break;
397
398 case GDF_16BIT_565RGB:
399 while (count--) {
400 c = *s;
401 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
402 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
403 rows--; dest += VIDEO_LINE_LEN) {
404 u8 bits = *cdat++;
405
406 ((u32 *) dest)[0] =
407 SHORTSWAP32((video_font_draw_table16
408 [bits >> 6] & eorx) ^
409 bgx);
410 ((u32 *) dest)[1] =
411 SHORTSWAP32((video_font_draw_table16
412 [bits >> 4 & 3] & eorx) ^
413 bgx);
414
415 if (VIDEO_FONT_WIDTH == 4)
416 continue;
417
418 ((u32 *) dest)[2] =
419 SHORTSWAP32((video_font_draw_table16
420 [bits >> 2 & 3] & eorx) ^
421 bgx);
422 ((u32 *) dest)[3] =
423 SHORTSWAP32((video_font_draw_table16
424 [bits & 3] & eorx) ^
425 bgx);
426 }
427 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
428 s++;
429 }
430 break;
431
432 case GDF_32BIT_X888RGB:
433 while (count--) {
434 c = *s;
435 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
436 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
437 rows--; dest += VIDEO_LINE_LEN) {
438 u8 bits = *cdat++;
439
440 ((u32 *) dest)[0] =
441 SWAP32((video_font_draw_table32
442 [bits >> 4][0] & eorx) ^ bgx);
443 ((u32 *) dest)[1] =
444 SWAP32((video_font_draw_table32
445 [bits >> 4][1] & eorx) ^ bgx);
446 ((u32 *) dest)[2] =
447 SWAP32((video_font_draw_table32
448 [bits >> 4][2] & eorx) ^ bgx);
449 ((u32 *) dest)[3] =
450 SWAP32((video_font_draw_table32
451 [bits >> 4][3] & eorx) ^ bgx);
452
453
454 if (VIDEO_FONT_WIDTH == 4)
455 continue;
456
457 ((u32 *) dest)[4] =
458 SWAP32((video_font_draw_table32
459 [bits & 15][0] & eorx) ^ bgx);
460 ((u32 *) dest)[5] =
461 SWAP32((video_font_draw_table32
462 [bits & 15][1] & eorx) ^ bgx);
463 ((u32 *) dest)[6] =
464 SWAP32((video_font_draw_table32
465 [bits & 15][2] & eorx) ^ bgx);
466 ((u32 *) dest)[7] =
467 SWAP32((video_font_draw_table32
468 [bits & 15][3] & eorx) ^ bgx);
469 }
470 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
471 s++;
472 }
473 break;
474
475 case GDF_24BIT_888RGB:
476 while (count--) {
477 c = *s;
478 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
479 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
480 rows--; dest += VIDEO_LINE_LEN) {
481 u8 bits = *cdat++;
482
483 ((u32 *) dest)[0] =
484 (video_font_draw_table24[bits >> 4][0]
485 & eorx) ^ bgx;
486 ((u32 *) dest)[1] =
487 (video_font_draw_table24[bits >> 4][1]
488 & eorx) ^ bgx;
489 ((u32 *) dest)[2] =
490 (video_font_draw_table24[bits >> 4][2]
491 & eorx) ^ bgx;
492
493 if (VIDEO_FONT_WIDTH == 4)
494 continue;
495
496 ((u32 *) dest)[3] =
497 (video_font_draw_table24[bits & 15][0]
498 & eorx) ^ bgx;
499 ((u32 *) dest)[4] =
500 (video_font_draw_table24[bits & 15][1]
501 & eorx) ^ bgx;
502 ((u32 *) dest)[5] =
503 (video_font_draw_table24[bits & 15][2]
504 & eorx) ^ bgx;
505 }
506 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
507 s++;
508 }
509 break;
510 }
511}
512
513static inline void video_drawstring(int xx, int yy, unsigned char *s)
514{
515 video_drawchars(xx, yy, s, strlen((char *) s));
516}
517
518static void video_putchar(int xx, int yy, unsigned char c)
519{
520 video_drawchars(xx, yy + video_logo_height, &c, 1);
521}
522
523#if defined(CONFIG_VIDEO_SW_CURSOR)
524static void video_set_cursor(void)
525{
526 if (cursor_state)
527 console_cursor(0);
528 console_cursor(1);
529}
530
531static void video_invertchar(int xx, int yy)
532{
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;
537 int x, y;
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;
541 *dest = ~*dest;
542 }
543 }
544}
545
546void console_cursor(int state)
547{
548 if (cursor_state != state) {
549 if (cursor_state) {
550
551 video_invertchar(old_col * VIDEO_FONT_WIDTH,
552 old_row * VIDEO_FONT_HEIGHT +
553 video_logo_height);
554 } else {
555
556 video_invertchar(console_col * VIDEO_FONT_WIDTH,
557 console_row * VIDEO_FONT_HEIGHT +
558 video_logo_height);
559 old_col = console_col;
560 old_row = console_row;
561 }
562 cursor_state = state;
563 }
564 if (cfb_do_flush_cache)
565 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
566}
567#endif
568
569#ifndef VIDEO_HW_RECTFILL
570static void memsetl(int *p, int c, int v)
571{
572 while (c--)
573 *(p++) = v;
574}
575#endif
576
577#ifndef VIDEO_HW_BITBLT
578static void memcpyl(int *d, int *s, int c)
579{
580 while (c--)
581 *(d++) = *(s++);
582}
583#endif
584
585static void console_clear_line(int line, int begin, int end)
586{
587#ifdef VIDEO_HW_RECTFILL
588 video_hw_rectfill(VIDEO_PIXEL_SIZE,
589 VIDEO_FONT_WIDTH * begin,
590 video_logo_height +
591 VIDEO_FONT_HEIGHT * line,
592 VIDEO_FONT_WIDTH * (end - begin + 1),
593 VIDEO_FONT_HEIGHT,
594 bgx
595 );
596#else
597 if (begin == 0 && (end + 1) == CONSOLE_COLS) {
598 memsetl(CONSOLE_ROW_FIRST +
599 CONSOLE_ROW_SIZE * line,
600 CONSOLE_ROW_SIZE >> 2,
601 bgx
602 );
603 } else {
604 void *offset;
605 int i, size;
606
607 offset = CONSOLE_ROW_FIRST +
608 CONSOLE_ROW_SIZE * line +
609 VIDEO_FONT_WIDTH *
610 VIDEO_PIXEL_SIZE * begin;
611 size = VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE * (end - begin + 1);
612 size >>= 2;
613
614 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
615 memsetl(offset + i * VIDEO_LINE_LEN, size, bgx);
616 }
617#endif
618}
619
620static void console_scrollup(void)
621{
622 const int rows = CONFIG_CONSOLE_SCROLL_LINES;
623 int i;
624
625
626
627#ifdef VIDEO_HW_BITBLT
628 video_hw_bitblt(VIDEO_PIXEL_SIZE,
629 0,
630 video_logo_height +
631 VIDEO_FONT_HEIGHT * rows,
632 0,
633 video_logo_height,
634 VIDEO_VISIBLE_COLS,
635 VIDEO_VISIBLE_ROWS
636 - video_logo_height
637 - VIDEO_FONT_HEIGHT * rows
638 );
639#else
640 memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_FIRST + rows * CONSOLE_ROW_SIZE,
641 (CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows) >> 2);
642#endif
643
644 for (i = 1; i <= rows; i++)
645 console_clear_line(CONSOLE_ROWS - i, 0, CONSOLE_COLS - 1);
646
647
648 console_row -= rows;
649}
650
651static void console_back(void)
652{
653 console_col--;
654
655 if (console_col < 0) {
656 console_col = CONSOLE_COLS - 1;
657 console_row--;
658 if (console_row < 0)
659 console_row = 0;
660 }
661}
662
663#ifdef CONFIG_CFB_CONSOLE_ANSI
664
665static void console_clear(void)
666{
667#ifdef VIDEO_HW_RECTFILL
668 video_hw_rectfill(VIDEO_PIXEL_SIZE,
669 0,
670 video_logo_height,
671 VIDEO_VISIBLE_COLS,
672 VIDEO_VISIBLE_ROWS,
673 bgx
674 );
675#else
676 memsetl(CONSOLE_ROW_FIRST, CONSOLE_SIZE, bgx);
677#endif
678}
679
680static void console_cursor_fix(void)
681{
682 if (console_row < 0)
683 console_row = 0;
684 if (console_row >= CONSOLE_ROWS)
685 console_row = CONSOLE_ROWS - 1;
686 if (console_col < 0)
687 console_col = 0;
688 if (console_col >= CONSOLE_COLS)
689 console_col = CONSOLE_COLS - 1;
690}
691
692static void console_cursor_up(int n)
693{
694 console_row -= n;
695 console_cursor_fix();
696}
697
698static void console_cursor_down(int n)
699{
700 console_row += n;
701 console_cursor_fix();
702}
703
704static void console_cursor_left(int n)
705{
706 console_col -= n;
707 console_cursor_fix();
708}
709
710static void console_cursor_right(int n)
711{
712 console_col += n;
713 console_cursor_fix();
714}
715
716static void console_cursor_set_position(int row, int col)
717{
718 if (console_row != -1)
719 console_row = row;
720 if (console_col != -1)
721 console_col = col;
722 console_cursor_fix();
723}
724
725static void console_previousline(int n)
726{
727
728 console_row -= n;
729 console_cursor_fix();
730}
731
732static void console_swap_colors(void)
733{
734 eorx = fgx;
735 fgx = bgx;
736 bgx = eorx;
737 eorx = fgx ^ bgx;
738}
739
740static inline int console_cursor_is_visible(void)
741{
742 return !ansi_cursor_hidden;
743}
744#else
745static inline int console_cursor_is_visible(void)
746{
747 return 1;
748}
749#endif
750
751static void console_newline(int n)
752{
753 console_row += n;
754 console_col = 0;
755
756
757 if (console_row >= CONSOLE_ROWS) {
758
759 console_scrollup();
760 }
761}
762
763static void console_cr(void)
764{
765 console_col = 0;
766}
767
768static void parse_putc(const char c)
769{
770 static int nl = 1;
771
772 if (console_cursor_is_visible())
773 CURSOR_OFF;
774
775 switch (c) {
776 case 13:
777 console_cr();
778 break;
779
780 case '\n':
781 if (console_col || (!console_col && nl))
782 console_newline(1);
783 nl = 1;
784 break;
785
786 case 9:
787 console_col |= 0x0008;
788 console_col &= ~0x0007;
789
790 if (console_col >= CONSOLE_COLS)
791 console_newline(1);
792 break;
793
794 case 8:
795 console_back();
796 break;
797
798 case 7:
799 break;
800
801 default:
802 video_putchar(console_col * VIDEO_FONT_WIDTH,
803 console_row * VIDEO_FONT_HEIGHT, c);
804 console_col++;
805
806
807 if (console_col >= CONSOLE_COLS) {
808 console_newline(1);
809 nl = 0;
810 }
811 }
812
813 if (console_cursor_is_visible())
814 CURSOR_SET;
815}
816
817static void cfb_video_putc(struct stdio_dev *dev, const char c)
818{
819#ifdef CONFIG_CFB_CONSOLE_ANSI
820 int i;
821
822 if (c == 27) {
823 for (i = 0; i < ansi_buf_size; ++i)
824 parse_putc(ansi_buf[i]);
825 ansi_buf[0] = 27;
826 ansi_buf_size = 1;
827 return;
828 }
829
830 if (ansi_buf_size > 0) {
831
832
833
834
835
836
837
838
839
840
841 int next = 0;
842
843 int flush = 0;
844 int fail = 0;
845
846 int num1 = 0;
847 int num2 = 0;
848 int cchar = 0;
849
850 ansi_buf[ansi_buf_size++] = c;
851
852 if (ansi_buf_size >= sizeof(ansi_buf))
853 fail = 1;
854
855 for (i = 0; i < ansi_buf_size; ++i) {
856 if (fail)
857 break;
858
859 switch (next) {
860 case 0:
861 if (ansi_buf[i] == 27)
862 next = 1;
863 else
864 fail = 1;
865 break;
866
867 case 1:
868 if (ansi_buf[i] == '[')
869 next = 2;
870 else
871 fail = 1;
872 break;
873
874 case 2:
875 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
876 num1 = ansi_buf[i]-'0';
877 next = 3;
878 } else if (ansi_buf[i] != '?') {
879 --i;
880 num1 = 1;
881 next = 4;
882 }
883 break;
884
885 case 3:
886 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
887 num1 *= 10;
888 num1 += ansi_buf[i]-'0';
889 } else {
890 --i;
891 next = 4;
892 }
893 break;
894
895 case 4:
896 if (ansi_buf[i] != ';') {
897 --i;
898 next = 7;
899 } else
900 next = 5;
901 break;
902
903 case 5:
904 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
905 num2 = ansi_buf[i]-'0';
906 next = 6;
907 } else
908 fail = 1;
909 break;
910
911 case 6:
912 if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
913 num2 *= 10;
914 num2 += ansi_buf[i]-'0';
915 } else {
916 --i;
917 next = 7;
918 }
919 break;
920
921 case 7:
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') {
928 cchar = ansi_buf[i];
929 flush = 1;
930 } else
931 fail = 1;
932 break;
933 }
934 }
935
936 if (fail) {
937 for (i = 0; i < ansi_buf_size; ++i)
938 parse_putc(ansi_buf[i]);
939 ansi_buf_size = 0;
940 return;
941 }
942
943 if (flush) {
944 if (!ansi_cursor_hidden)
945 CURSOR_OFF;
946 ansi_buf_size = 0;
947 switch (cchar) {
948 case 'A':
949
950 console_cursor_up(num1);
951 break;
952 case 'B':
953
954 console_cursor_down(num1);
955 break;
956 case 'C':
957
958 console_cursor_right(num1);
959 break;
960 case 'D':
961
962 console_cursor_left(num1);
963 break;
964 case 'E':
965
966 console_previousline(num1);
967 break;
968 case 'F':
969
970 console_newline(num1);
971 break;
972 case 'G':
973
974 console_cursor_set_position(-1, num1-1);
975 break;
976 case 'H':
977
978 console_cursor_set_position(num1-1, num2-1);
979 break;
980 case 'J':
981
982 console_clear();
983 console_cursor_set_position(0, 0);
984 break;
985 case 'K':
986
987 if (num1 == 0)
988 console_clear_line(console_row,
989 console_col,
990 CONSOLE_COLS-1);
991 else if (num1 == 1)
992 console_clear_line(console_row,
993 0, console_col);
994 else
995 console_clear_line(console_row,
996 0, CONSOLE_COLS-1);
997 break;
998 case 'h':
999 ansi_cursor_hidden = 0;
1000 break;
1001 case 'l':
1002 ansi_cursor_hidden = 1;
1003 break;
1004 case 'm':
1005 if (num1 == 0) {
1006 if (ansi_colors_need_revert) {
1007 console_swap_colors();
1008 ansi_colors_need_revert = 0;
1009 }
1010 } else if (num1 == 7) {
1011 if (!ansi_colors_need_revert) {
1012 console_swap_colors();
1013 ansi_colors_need_revert = 1;
1014 }
1015 }
1016 break;
1017 }
1018 if (!ansi_cursor_hidden)
1019 CURSOR_SET;
1020 }
1021 } else {
1022 parse_putc(c);
1023 }
1024#else
1025 parse_putc(c);
1026#endif
1027 if (cfb_do_flush_cache)
1028 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
1029}
1030
1031static void cfb_video_puts(struct stdio_dev *dev, const char *s)
1032{
1033 int flush = cfb_do_flush_cache;
1034 int count = strlen(s);
1035
1036
1037 cfb_do_flush_cache = 0;
1038
1039 while (count--)
1040 cfb_video_putc(dev, *s++);
1041
1042 if (flush) {
1043 cfb_do_flush_cache = flush;
1044 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
1045 }
1046}
1047
1048
1049
1050
1051
1052
1053__weak void video_set_lut(unsigned int index, unsigned char r,
1054 unsigned char g, unsigned char b)
1055{
1056}
1057
1058#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
1059
1060#define FILL_8BIT_332RGB(r,g,b) { \
1061 *fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \
1062 fb ++; \
1063}
1064
1065#define FILL_15BIT_555RGB(r,g,b) { \
1066 *(unsigned short *)fb = \
1067 SWAP16((unsigned short)(((r>>3)<<10) | \
1068 ((g>>3)<<5) | \
1069 (b>>3))); \
1070 fb += 2; \
1071}
1072
1073#define FILL_16BIT_565RGB(r,g,b) { \
1074 *(unsigned short *)fb = \
1075 SWAP16((unsigned short)((((r)>>3)<<11)| \
1076 (((g)>>2)<<5) | \
1077 ((b)>>3))); \
1078 fb += 2; \
1079}
1080
1081#define FILL_32BIT_X888RGB(r,g,b) { \
1082 *(unsigned long *)fb = \
1083 SWAP32((unsigned long)(((r<<16) | \
1084 (g<<8) | \
1085 b))); \
1086 fb += 4; \
1087}
1088
1089#ifdef VIDEO_FB_LITTLE_ENDIAN
1090#define FILL_24BIT_888RGB(r,g,b) { \
1091 fb[0] = b; \
1092 fb[1] = g; \
1093 fb[2] = r; \
1094 fb += 3; \
1095}
1096#else
1097#define FILL_24BIT_888RGB(r,g,b) { \
1098 fb[0] = r; \
1099 fb[1] = g; \
1100 fb[2] = b; \
1101 fb += 3; \
1102}
1103#endif
1104
1105#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1106static inline void fill_555rgb_pswap(uchar *fb, int x, u8 r, u8 g, u8 b)
1107{
1108 ushort *dst = (ushort *) fb;
1109 ushort color = (ushort) (((r >> 3) << 10) |
1110 ((g >> 3) << 5) |
1111 (b >> 3));
1112 if (x & 1)
1113 *(--dst) = color;
1114 else
1115 *(++dst) = color;
1116}
1117#endif
1118
1119
1120
1121
1122
1123#ifdef CONFIG_VIDEO_BMP_RLE8
1124
1125struct palette {
1126 union {
1127 unsigned short w;
1128 unsigned int dw;
1129 } ce;
1130};
1131
1132
1133
1134
1135static void draw_bitmap(uchar **fb, uchar *bm, struct palette *p,
1136 int cnt, int enc)
1137{
1138 ulong addr = (ulong) *fb;
1139 int *off;
1140 int enc_off = 1;
1141 int i;
1142
1143
1144
1145
1146
1147 off = enc ? &enc_off : &i;
1148
1149 switch (VIDEO_DATA_FORMAT) {
1150 case GDF__8BIT_INDEX:
1151 for (i = 0; i < cnt; i++)
1152 *(unsigned char *) addr++ = bm[*off];
1153 break;
1154 case GDF_15BIT_555RGB:
1155 case GDF_16BIT_565RGB:
1156
1157 for (i = 0; i < cnt; i++) {
1158 *(unsigned short *) addr = p[bm[*off]].ce.w;
1159 addr += 2;
1160 }
1161 break;
1162 case GDF_32BIT_X888RGB:
1163 for (i = 0; i < cnt; i++) {
1164 *(unsigned long *) addr = p[bm[*off]].ce.dw;
1165 addr += 4;
1166 }
1167 break;
1168 }
1169 *fb = (uchar *) addr;
1170}
1171
1172static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff,
1173 int width, int height)
1174{
1175 unsigned char *bm;
1176 unsigned char *fbp;
1177 unsigned int cnt, runlen;
1178 int decode = 1;
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;
1184 int pixels = 0;
1185
1186 x = 0;
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 +
1192 xoff * bpp);
1193
1194 bm = (uchar *) img + __le32_to_cpu(img->header.data_offset);
1195
1196
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);
1202 }
1203 break;
1204 case GDF_15BIT_555RGB:
1205 case GDF_16BIT_565RGB:
1206 if (VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) {
1207 green_shift = 3;
1208 red_off = 10;
1209 } else {
1210 green_shift = 2;
1211 red_off = 11;
1212 }
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) |
1218 cte.blue >> 3));
1219 }
1220 break;
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) |
1225 (cte.green << 8) |
1226 cte.blue);
1227 }
1228 break;
1229 default:
1230 printf("RLE Bitmap unsupported in video mode 0x%x\n",
1231 VIDEO_DATA_FORMAT);
1232 return -1;
1233 }
1234
1235 while (decode) {
1236 switch (bm[0]) {
1237 case 0:
1238 switch (bm[1]) {
1239 case 0:
1240
1241 bm += 2;
1242 x = 0;
1243 y--;
1244 fbp = (unsigned char *)
1245 ((unsigned int) video_fb_address +
1246 (y + yoff) * VIDEO_LINE_LEN +
1247 xoff * bpp);
1248 continue;
1249 case 1:
1250
1251 decode = 0;
1252 break;
1253 case 2:
1254
1255 x += bm[2];
1256 y -= bm[3];
1257 fbp = (unsigned char *)
1258 ((unsigned int) video_fb_address +
1259 (y + yoff) * VIDEO_LINE_LEN +
1260 xoff * bpp);
1261 bm += 4;
1262 break;
1263 default:
1264
1265 cnt = bm[1];
1266 runlen = cnt;
1267 pixels += cnt;
1268 if (pixels > limit)
1269 goto error;
1270
1271 bm += 2;
1272 if (y < height) {
1273 if (x >= width) {
1274 x += runlen;
1275 goto next_run;
1276 }
1277 if (x + runlen > width)
1278 cnt = width - x;
1279 draw_bitmap(&fbp, bm, p, cnt, 0);
1280 x += runlen;
1281 }
1282next_run:
1283 bm += runlen;
1284 if (runlen & 1)
1285 bm++;
1286 }
1287 break;
1288 default:
1289
1290 cnt = bm[0];
1291 runlen = cnt;
1292 pixels += cnt;
1293 if (pixels > limit)
1294 goto error;
1295
1296 if (y < height) {
1297 if (x >= width) {
1298 x += runlen;
1299 bm += 2;
1300 continue;
1301 }
1302 if (x + runlen > width)
1303 cnt = width - x;
1304 draw_bitmap(&fbp, bm, p, cnt, 1);
1305 x += runlen;
1306 }
1307 bm += 2;
1308 break;
1309 }
1310 }
1311 return 0;
1312error:
1313 printf("Error: Too much encoded pixel data, validate your bitmap\n");
1314 return -1;
1315}
1316#endif
1317
1318
1319
1320
1321int video_display_bitmap(ulong bmp_image, int x, int y)
1322{
1323 ushort xcount, ycount;
1324 uchar *fb;
1325 struct bmp_image *bmp = (struct bmp_image *)bmp_image;
1326 uchar *bmap;
1327 ushort padded_line;
1328 unsigned long width, height, bpp;
1329 unsigned colors;
1330 unsigned long compression;
1331 struct bmp_color_table_entry cte;
1332
1333#ifdef CONFIG_VIDEO_BMP_GZIP
1334 unsigned char *dst = NULL;
1335 ulong len;
1336#endif
1337
1338 WATCHDOG_RESET();
1339
1340 if (!((bmp->header.signature[0] == 'B') &&
1341 (bmp->header.signature[1] == 'M'))) {
1342
1343#ifdef CONFIG_VIDEO_BMP_GZIP
1344
1345
1346
1347 len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
1348 dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
1349 if (dst == NULL) {
1350 printf("Error: malloc in gunzip failed!\n");
1351 return 1;
1352 }
1353
1354
1355
1356
1357 if (gunzip(dst+2, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE-2,
1358 (uchar *) bmp_image,
1359 &len) != 0) {
1360 printf("Error: no valid bmp or bmp.gz image at %lx\n",
1361 bmp_image);
1362 free(dst);
1363 return 1;
1364 }
1365 if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
1366 printf("Image could be truncated "
1367 "(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
1368 }
1369
1370
1371
1372
1373 bmp = (struct bmp_image *)(dst+2);
1374
1375 if (!((bmp->header.signature[0] == 'B') &&
1376 (bmp->header.signature[1] == 'M'))) {
1377 printf("Error: no valid bmp.gz image at %lx\n",
1378 bmp_image);
1379 free(dst);
1380 return 1;
1381 }
1382#else
1383 printf("Error: no valid bmp image at %lx\n", bmp_image);
1384 return 1;
1385#endif
1386 }
1387
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);
1393
1394 debug("Display-bmp: %ld x %ld with %d colors\n",
1395 width, height, colors);
1396
1397 if (compression != BMP_BI_RGB
1398#ifdef CONFIG_VIDEO_BMP_RLE8
1399 && compression != BMP_BI_RLE8
1400#endif
1401 ) {
1402 printf("Error: compression type %ld not supported\n",
1403 compression);
1404#ifdef CONFIG_VIDEO_BMP_GZIP
1405 if (dst)
1406 free(dst);
1407#endif
1408 return 1;
1409 }
1410
1411 padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
1412
1413#ifdef CONFIG_SPLASH_SCREEN_ALIGN
1414 if (x == BMP_ALIGN_CENTER)
1415 x = max(0, (int)(VIDEO_VISIBLE_COLS - width) / 2);
1416 else if (x < 0)
1417 x = max(0, (int)(VIDEO_VISIBLE_COLS - width + x + 1));
1418
1419 if (y == BMP_ALIGN_CENTER)
1420 y = max(0, (int)(VIDEO_VISIBLE_ROWS - height) / 2);
1421 else if (y < 0)
1422 y = max(0, (int)(VIDEO_VISIBLE_ROWS - height + y + 1));
1423#endif
1424
1425
1426
1427
1428
1429 if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS))
1430 return 0;
1431
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;
1436
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);
1441
1442#ifdef CONFIG_VIDEO_BMP_RLE8
1443 if (compression == BMP_BI_RLE8) {
1444 return display_rle8_bitmap(bmp, x, y, width, height);
1445 }
1446#endif
1447
1448
1449 switch (le16_to_cpu(bmp->header.bit_count)) {
1450 case 4:
1451 padded_line -= width / 2;
1452 ycount = height;
1453
1454 switch (VIDEO_DATA_FORMAT) {
1455 case GDF_32BIT_X888RGB:
1456 while (ycount--) {
1457 WATCHDOG_RESET();
1458
1459
1460
1461
1462 for (xcount = 0; xcount < width; xcount++) {
1463 uchar idx;
1464
1465 if (xcount & 1) {
1466 idx = *bmap & 0xF;
1467 bmap++;
1468 } else
1469 idx = *bmap >> 4;
1470 cte = bmp->color_table[idx];
1471 FILL_32BIT_X888RGB(cte.red, cte.green,
1472 cte.blue);
1473 }
1474 bmap += padded_line;
1475 fb -= VIDEO_LINE_LEN + width *
1476 VIDEO_PIXEL_SIZE;
1477 }
1478 break;
1479 default:
1480 puts("4bpp bitmap unsupported with current "
1481 "video mode\n");
1482 break;
1483 }
1484 break;
1485
1486 case 8:
1487 padded_line -= width;
1488 if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
1489
1490 for (xcount = 0; xcount < colors; ++xcount) {
1491 cte = bmp->color_table[xcount];
1492 video_set_lut(xcount, cte.red, cte.green,
1493 cte.blue);
1494 }
1495 }
1496 ycount = height;
1497 switch (VIDEO_DATA_FORMAT) {
1498 case GDF__8BIT_INDEX:
1499 while (ycount--) {
1500 WATCHDOG_RESET();
1501 xcount = width;
1502 while (xcount--) {
1503 *fb++ = *bmap++;
1504 }
1505 bmap += padded_line;
1506 fb -= VIDEO_LINE_LEN + width *
1507 VIDEO_PIXEL_SIZE;
1508 }
1509 break;
1510 case GDF__8BIT_332RGB:
1511 while (ycount--) {
1512 WATCHDOG_RESET();
1513 xcount = width;
1514 while (xcount--) {
1515 cte = bmp->color_table[*bmap++];
1516 FILL_8BIT_332RGB(cte.red, cte.green,
1517 cte.blue);
1518 }
1519 bmap += padded_line;
1520 fb -= VIDEO_LINE_LEN + width *
1521 VIDEO_PIXEL_SIZE;
1522 }
1523 break;
1524 case GDF_15BIT_555RGB:
1525 while (ycount--) {
1526#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1527 int xpos = x;
1528#endif
1529 WATCHDOG_RESET();
1530 xcount = width;
1531 while (xcount--) {
1532 cte = bmp->color_table[*bmap++];
1533#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1534 fill_555rgb_pswap(fb, xpos++, cte.red,
1535 cte.green,
1536 cte.blue);
1537 fb += 2;
1538#else
1539 FILL_15BIT_555RGB(cte.red, cte.green,
1540 cte.blue);
1541#endif
1542 }
1543 bmap += padded_line;
1544 fb -= VIDEO_LINE_LEN + width *
1545 VIDEO_PIXEL_SIZE;
1546 }
1547 break;
1548 case GDF_16BIT_565RGB:
1549 while (ycount--) {
1550 WATCHDOG_RESET();
1551 xcount = width;
1552 while (xcount--) {
1553 cte = bmp->color_table[*bmap++];
1554 FILL_16BIT_565RGB(cte.red, cte.green,
1555 cte.blue);
1556 }
1557 bmap += padded_line;
1558 fb -= VIDEO_LINE_LEN + width *
1559 VIDEO_PIXEL_SIZE;
1560 }
1561 break;
1562 case GDF_32BIT_X888RGB:
1563 while (ycount--) {
1564 WATCHDOG_RESET();
1565 xcount = width;
1566 while (xcount--) {
1567 cte = bmp->color_table[*bmap++];
1568 FILL_32BIT_X888RGB(cte.red, cte.green,
1569 cte.blue);
1570 }
1571 bmap += padded_line;
1572 fb -= VIDEO_LINE_LEN + width *
1573 VIDEO_PIXEL_SIZE;
1574 }
1575 break;
1576 case GDF_24BIT_888RGB:
1577 while (ycount--) {
1578 WATCHDOG_RESET();
1579 xcount = width;
1580 while (xcount--) {
1581 cte = bmp->color_table[*bmap++];
1582 FILL_24BIT_888RGB(cte.red, cte.green,
1583 cte.blue);
1584 }
1585 bmap += padded_line;
1586 fb -= VIDEO_LINE_LEN + width *
1587 VIDEO_PIXEL_SIZE;
1588 }
1589 break;
1590 }
1591 break;
1592 case 24:
1593 padded_line -= 3 * width;
1594 ycount = height;
1595 switch (VIDEO_DATA_FORMAT) {
1596 case GDF__8BIT_332RGB:
1597 while (ycount--) {
1598 WATCHDOG_RESET();
1599 xcount = width;
1600 while (xcount--) {
1601 FILL_8BIT_332RGB(bmap[2], bmap[1],
1602 bmap[0]);
1603 bmap += 3;
1604 }
1605 bmap += padded_line;
1606 fb -= VIDEO_LINE_LEN + width *
1607 VIDEO_PIXEL_SIZE;
1608 }
1609 break;
1610 case GDF_15BIT_555RGB:
1611 while (ycount--) {
1612#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1613 int xpos = x;
1614#endif
1615 WATCHDOG_RESET();
1616 xcount = width;
1617 while (xcount--) {
1618#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1619 fill_555rgb_pswap(fb, xpos++, bmap[2],
1620 bmap[1], bmap[0]);
1621 fb += 2;
1622#else
1623 FILL_15BIT_555RGB(bmap[2], bmap[1],
1624 bmap[0]);
1625#endif
1626 bmap += 3;
1627 }
1628 bmap += padded_line;
1629 fb -= VIDEO_LINE_LEN + width *
1630 VIDEO_PIXEL_SIZE;
1631 }
1632 break;
1633 case GDF_16BIT_565RGB:
1634 while (ycount--) {
1635 WATCHDOG_RESET();
1636 xcount = width;
1637 while (xcount--) {
1638 FILL_16BIT_565RGB(bmap[2], bmap[1],
1639 bmap[0]);
1640 bmap += 3;
1641 }
1642 bmap += padded_line;
1643 fb -= VIDEO_LINE_LEN + width *
1644 VIDEO_PIXEL_SIZE;
1645 }
1646 break;
1647 case GDF_32BIT_X888RGB:
1648 while (ycount--) {
1649 WATCHDOG_RESET();
1650 xcount = width;
1651 while (xcount--) {
1652 FILL_32BIT_X888RGB(bmap[2], bmap[1],
1653 bmap[0]);
1654 bmap += 3;
1655 }
1656 bmap += padded_line;
1657 fb -= VIDEO_LINE_LEN + width *
1658 VIDEO_PIXEL_SIZE;
1659 }
1660 break;
1661 case GDF_24BIT_888RGB:
1662 while (ycount--) {
1663 WATCHDOG_RESET();
1664 xcount = width;
1665 while (xcount--) {
1666 FILL_24BIT_888RGB(bmap[2], bmap[1],
1667 bmap[0]);
1668 bmap += 3;
1669 }
1670 bmap += padded_line;
1671 fb -= VIDEO_LINE_LEN + width *
1672 VIDEO_PIXEL_SIZE;
1673 }
1674 break;
1675 default:
1676 printf("Error: 24 bits/pixel bitmap incompatible "
1677 "with current video mode\n");
1678 break;
1679 }
1680 break;
1681 default:
1682 printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
1683 le16_to_cpu(bmp->header.bit_count));
1684 break;
1685 }
1686
1687#ifdef CONFIG_VIDEO_BMP_GZIP
1688 if (dst) {
1689 free(dst);
1690 }
1691#endif
1692
1693 if (cfb_do_flush_cache)
1694 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
1695 return (0);
1696}
1697#endif
1698
1699
1700#ifdef CONFIG_VIDEO_LOGO
1701static int video_logo_xpos;
1702static int video_logo_ypos;
1703
1704static void plot_logo_or_black(void *screen, int x, int y, int black);
1705
1706static void logo_plot(void *screen, int x, int y)
1707{
1708 plot_logo_or_black(screen, x, y, 0);
1709}
1710
1711static void logo_black(void)
1712{
1713 plot_logo_or_black(video_fb_address, video_logo_xpos, video_logo_ypos,
1714 1);
1715}
1716
1717static int do_clrlogo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1718{
1719 if (argc != 1)
1720 return cmd_usage(cmdtp);
1721
1722 logo_black();
1723 return 0;
1724}
1725
1726U_BOOT_CMD(
1727 clrlogo, 1, 0, do_clrlogo,
1728 "fill the boot logo area with black",
1729 " "
1730 );
1731
1732static void plot_logo_or_black(void *screen, int x, int y, int black)
1733{
1734
1735 int xcount, i;
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;
1741
1742#ifdef CONFIG_SPLASH_SCREEN_ALIGN
1743 if (x == BMP_ALIGN_CENTER)
1744 x = max(0, (int)(VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH) / 2);
1745 else if (x < 0)
1746 x = max(0, (int)(VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH + x + 1));
1747
1748 if (y == BMP_ALIGN_CENTER)
1749 y = max(0, (int)(VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT) / 2);
1750 else if (y < 0)
1751 y = max(0, (int)(VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1));
1752#endif
1753
1754 dest = (unsigned char *)screen + y * VIDEO_LINE_LEN + x * VIDEO_PIXEL_SIZE;
1755
1756#ifdef CONFIG_VIDEO_BMP_LOGO
1757 source = bmp_logo_bitmap;
1758
1759
1760 logo_red = malloc(BMP_LOGO_COLORS);
1761 logo_green = malloc(BMP_LOGO_COLORS);
1762 logo_blue = malloc(BMP_LOGO_COLORS);
1763
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;
1768 }
1769#else
1770 source = linux_logo;
1771 logo_red = linux_logo_red;
1772 logo_green = linux_logo_green;
1773 logo_blue = linux_logo_blue;
1774#endif
1775
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],
1780 logo_blue[i]);
1781 }
1782 }
1783
1784 while (ycount--) {
1785#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1786 int xpos = x;
1787#endif
1788 xcount = VIDEO_LOGO_WIDTH;
1789 while (xcount--) {
1790 if (black) {
1791 r = 0x00;
1792 g = 0x00;
1793 b = 0x00;
1794 } else {
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];
1798 }
1799
1800 switch (VIDEO_DATA_FORMAT) {
1801 case GDF__8BIT_INDEX:
1802 *dest = *source;
1803 break;
1804 case GDF__8BIT_332RGB:
1805 *dest = ((r >> 5) << 5) |
1806 ((g >> 5) << 2) |
1807 (b >> 6);
1808 break;
1809 case GDF_15BIT_555RGB:
1810#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1811 fill_555rgb_pswap(dest, xpos++, r, g, b);
1812#else
1813 *(unsigned short *) dest =
1814 SWAP16((unsigned short) (
1815 ((r >> 3) << 10) |
1816 ((g >> 3) << 5) |
1817 (b >> 3)));
1818#endif
1819 break;
1820 case GDF_16BIT_565RGB:
1821 *(unsigned short *) dest =
1822 SWAP16((unsigned short) (
1823 ((r >> 3) << 11) |
1824 ((g >> 2) << 5) |
1825 (b >> 3)));
1826 break;
1827 case GDF_32BIT_X888RGB:
1828 *(unsigned long *) dest =
1829 SWAP32((unsigned long) (
1830 (r << 16) |
1831 (g << 8) |
1832 b));
1833 break;
1834 case GDF_24BIT_888RGB:
1835#ifdef VIDEO_FB_LITTLE_ENDIAN
1836 dest[0] = b;
1837 dest[1] = g;
1838 dest[2] = r;
1839#else
1840 dest[0] = r;
1841 dest[1] = g;
1842 dest[2] = b;
1843#endif
1844 break;
1845 }
1846 source++;
1847 dest += VIDEO_PIXEL_SIZE;
1848 }
1849 dest += skip;
1850 }
1851#ifdef CONFIG_VIDEO_BMP_LOGO
1852 free(logo_red);
1853 free(logo_green);
1854 free(logo_blue);
1855#endif
1856}
1857
1858static void *video_logo(void)
1859{
1860 char info[128];
1861 __maybe_unused int y_off = 0;
1862 __maybe_unused ulong addr;
1863 __maybe_unused char *s;
1864 __maybe_unused int len, space;
1865
1866 splash_get_pos(&video_logo_xpos, &video_logo_ypos);
1867
1868#ifdef CONFIG_SPLASH_SCREEN
1869 s = getenv("splashimage");
1870 if (s != NULL) {
1871 splash_screen_prepare();
1872 addr = simple_strtoul(s, NULL, 16);
1873
1874 if (video_display_bitmap(addr,
1875 video_logo_xpos,
1876 video_logo_ypos) == 0) {
1877 video_logo_height = 0;
1878 return ((void *) (video_fb_address));
1879 }
1880 }
1881#endif
1882
1883 logo_plot(video_fb_address, video_logo_xpos, video_logo_ypos);
1884
1885#ifdef CONFIG_SPLASH_SCREEN_ALIGN
1886
1887
1888
1889
1890 if (video_logo_xpos || video_logo_ypos) {
1891
1892
1893
1894
1895
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;
1901
1902 return video_fb_address + video_logo_height * VIDEO_LINE_LEN;
1903 }
1904#endif
1905 if (board_cfb_skip())
1906 return 0;
1907
1908 sprintf(info, " %s", version_string);
1909
1910#ifndef CONFIG_HIDE_LOGO_VERSION
1911 space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
1912 len = strlen(info);
1913
1914 if (len > space) {
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);
1920 y_off = 1;
1921 } else
1922 video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);
1923
1924#ifdef CONFIG_CONSOLE_EXTRA_INFO
1925 {
1926 int i, n =
1927 ((video_logo_height -
1928 VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
1929
1930 for (i = 1; i < n; i++) {
1931 video_get_info_str(i, info);
1932 if (!*info)
1933 continue;
1934
1935 len = strlen(info);
1936 if (len > space) {
1937 video_drawchars(VIDEO_INFO_X,
1938 VIDEO_INFO_Y +
1939 (i + y_off) *
1940 VIDEO_FONT_HEIGHT,
1941 (uchar *) info, space);
1942 y_off++;
1943 video_drawchars(VIDEO_INFO_X +
1944 VIDEO_FONT_WIDTH,
1945 VIDEO_INFO_Y +
1946 (i + y_off) *
1947 VIDEO_FONT_HEIGHT,
1948 (uchar *) info + space,
1949 len - space);
1950 } else {
1951 video_drawstring(VIDEO_INFO_X,
1952 VIDEO_INFO_Y +
1953 (i + y_off) *
1954 VIDEO_FONT_HEIGHT,
1955 (uchar *) info);
1956 }
1957 }
1958 }
1959#endif
1960#endif
1961
1962 return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
1963}
1964#endif
1965
1966static int cfb_fb_is_in_dram(void)
1967{
1968 bd_t *bd = gd->bd;
1969#if defined(CONFIG_ARM) || defined(CONFIG_AVR32) || defined(COFNIG_NDS32) || \
1970defined(CONFIG_SANDBOX) || defined(CONFIG_X86)
1971 ulong start, end;
1972 int i;
1973
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)
1979 return 1;
1980 }
1981#else
1982 if ((ulong)video_fb_address >= bd->bi_memstart &&
1983 (ulong)video_fb_address < bd->bi_memstart + bd->bi_memsize)
1984 return 1;
1985#endif
1986 return 0;
1987}
1988
1989void video_clear(void)
1990{
1991 if (!video_fb_address)
1992 return;
1993#ifdef VIDEO_HW_RECTFILL
1994 video_hw_rectfill(VIDEO_PIXEL_SIZE,
1995 0,
1996 0,
1997 VIDEO_VISIBLE_COLS,
1998 VIDEO_VISIBLE_ROWS,
1999 bgx
2000 );
2001#else
2002 memsetl(video_fb_address,
2003 (VIDEO_VISIBLE_ROWS * VIDEO_LINE_LEN) / sizeof(int), bgx);
2004#endif
2005}
2006
2007static int cfg_video_init(void)
2008{
2009 unsigned char color8;
2010
2011 pGD = video_hw_init();
2012 if (pGD == NULL)
2013 return -1;
2014
2015 video_fb_address = (void *) VIDEO_FB_ADRS;
2016
2017 cfb_do_flush_cache = cfb_fb_is_in_dram() && dcache_status();
2018
2019
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);
2028 fgx = 0x01010101;
2029 bgx = 0x00000000;
2030 break;
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) |
2036 color8;
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) |
2041 color8;
2042 break;
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));
2056 break;
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));
2070 break;
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;
2078 break;
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;
2088 break;
2089 }
2090 eorx = fgx ^ bgx;
2091
2092 video_clear();
2093
2094#ifdef CONFIG_VIDEO_LOGO
2095
2096 debug("Video: Drawing the logo ...\n");
2097 video_console_address = video_logo();
2098#else
2099 video_console_address = video_fb_address;
2100#endif
2101
2102
2103 console_col = 0;
2104 console_row = 0;
2105
2106 if (cfb_do_flush_cache)
2107 flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
2108
2109 return 0;
2110}
2111
2112
2113
2114
2115
2116__weak int board_video_skip(void)
2117{
2118
2119 return 0;
2120}
2121
2122int drv_video_init(void)
2123{
2124 struct stdio_dev console_dev;
2125 bool have_keyboard;
2126 bool __maybe_unused keyboard_ok = false;
2127
2128
2129 if (board_video_skip())
2130 return 0;
2131
2132
2133 if (cfg_video_init() == -1)
2134 return 0;
2135
2136 if (board_cfb_skip())
2137 return 0;
2138
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");
2144#else
2145 have_keyboard = true;
2146#endif
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);
2151#endif
2152 }
2153
2154
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;
2159 console_dev.puts = cfb_video_puts;
2160
2161#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
2162 if (have_keyboard && keyboard_ok) {
2163
2164 console_dev.flags |= DEV_FLAGS_INPUT;
2165 console_dev.tstc = VIDEO_TSTC_FCT;
2166 console_dev.getc = VIDEO_GETC_FCT;
2167 }
2168#endif
2169
2170 if (stdio_register(&console_dev) != 0)
2171 return 0;
2172
2173
2174 return 1;
2175}
2176
2177void video_position_cursor(unsigned col, unsigned row)
2178{
2179 console_col = min(col, CONSOLE_COLS - 1);
2180 console_row = min(row, CONSOLE_ROWS - 1);
2181}
2182
2183int video_get_pixel_width(void)
2184{
2185 return VIDEO_VISIBLE_COLS;
2186}
2187
2188int video_get_pixel_height(void)
2189{
2190 return VIDEO_VISIBLE_ROWS;
2191}
2192
2193int video_get_screen_rows(void)
2194{
2195 return CONSOLE_ROWS;
2196}
2197
2198int video_get_screen_columns(void)
2199{
2200 return CONSOLE_COLS;
2201}
2202