]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc8xx/lcd.c
* Patches by Udi Finkelstein, 2 June 2003:
[karo-tx-uboot.git] / cpu / mpc8xx / lcd.c
1 /*
2  * (C) Copyright 2001-2002
3  * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
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.
12  *
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.
17  *
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,
21  * MA 02111-1307 USA
22  */
23
24 /************************************************************************/
25 /* ** HEADER FILES                                                      */
26 /************************************************************************/
27
28 #include <config.h>
29 #include <common.h>
30 #include <watchdog.h>
31 #include <version.h>
32 #include <stdarg.h>
33 #include <lcdvideo.h>
34 #include <linux/types.h>
35 #include <devices.h>
36 #if defined(CONFIG_POST)
37 #include <post.h>
38 #endif
39 #include <lcd.h>
40
41 #ifdef CONFIG_LCD
42
43 /************************************************************************/
44 /* ** CONFIG STUFF -- should be moved to board config file              */
45 /************************************************************************/
46 #define CONFIG_LCD_LOGO
47 #define LCD_INFO                /* Display Logo, (C) and system info    */
48
49 #if defined(CONFIG_V37) || defined(CONFIG_EDT32F10)
50 #undef CONFIG_LCD_LOGO
51 #undef LCD_INFO
52 #endif
53
54 /* #define LCD_TEST_PATTERN */  /* color backgnd for frame/color adjust */
55 /* #define CFG_INVERT_COLORS */ /* Not needed - adjust vl_dp instead    */
56 /************************************************************************/
57
58 /************************************************************************/
59 /* ** BITMAP DISPLAY SUPPORT  -- should probably be moved elsewhere     */
60 /************************************************************************/
61
62 #if (CONFIG_COMMANDS & CFG_CMD_BMP)
63 #include <bmp_layout.h>
64 #endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) */
65
66 /************************************************************************/
67 /* ** FONT AND LOGO DATA                                                */
68 /************************************************************************/
69
70 #include <video_font.h>         /* Get font data, width and height      */
71
72 #ifdef CONFIG_LCD_LOGO
73 # include <bmp_logo.h>          /* Get logo data, width and height      */
74 #endif
75
76 /************************************************************************/
77 /************************************************************************/
78
79 /*
80  *  Information about displays we are using.  This is for configuring
81  *  the LCD controller and memory allocation.  Someone has to know what
82  *  is connected, as we can't autodetect anything.
83  */
84 #define CFG_HIGH        0       /* Pins are active high */
85 #define CFG_LOW         1       /* Pins are active low */
86
87 typedef struct vidinfo {
88     ushort      vl_col;         /* Number of columns (i.e. 640) */
89     ushort      vl_row;         /* Number of rows (i.e. 480) */
90     ushort      vl_width;       /* Width of display area in millimeters */
91     ushort      vl_height;      /* Height of display area in millimeters */
92
93     /* LCD configuration register.
94     */
95     u_char      vl_clkp;        /* Clock polarity */
96     u_char      vl_oep;         /* Output Enable polarity */
97     u_char      vl_hsp;         /* Horizontal Sync polarity */
98     u_char      vl_vsp;         /* Vertical Sync polarity */
99     u_char      vl_dp;          /* Data polarity */
100     u_char      vl_bpix;        /* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8 */
101     u_char      vl_lbw;         /* LCD Bus width, 0 = 4, 1 = 8 */
102     u_char      vl_splt;        /* Split display, 0 = single-scan, 1 = dual-scan */
103     u_char      vl_clor;        /* Color, 0 = mono, 1 = color */
104     u_char      vl_tft;         /* 0 = passive, 1 = TFT */
105
106     /* Horizontal control register.  Timing from data sheet.
107     */
108     ushort      vl_wbl;         /* Wait between lines */
109
110     /* Vertical control register.
111     */
112     u_char      vl_vpw;         /* Vertical sync pulse width */
113     u_char      vl_lcdac;       /* LCD AC timing */
114     u_char      vl_wbf;         /* Wait between frames */
115 } vidinfo_t;
116
117 #define LCD_MONOCHROME  0
118 #define LCD_COLOR2      1
119 #define LCD_COLOR4      2
120 #define LCD_COLOR8      3
121
122 /*----------------------------------------------------------------------*/
123 #ifdef CONFIG_KYOCERA_KCS057QV1AJ
124 /*
125  *  Kyocera KCS057QV1AJ-G23. Passive, color, single scan.
126  */
127 #define LCD_BPP LCD_COLOR4
128
129 static vidinfo_t panel_info = {
130     640, 480, 132, 99, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH,
131     LCD_BPP, 1, 0, 1, 0,  5, 0, 0, 0
132                 /* wbl, vpw, lcdac, wbf */
133 };
134 #endif /* CONFIG_KYOCERA_KCS057QV1AJ */
135 /*----------------------------------------------------------------------*/
136
137 /*----------------------------------------------------------------------*/
138 #ifdef CONFIG_HITACHI_SP19X001_Z1A
139 /*
140  *  Hitachi SP19X001-. Active, color, single scan.
141  */
142 static vidinfo_t panel_info = {
143     640, 480, 154, 116, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH,
144     LCD_COLOR8, 1, 0, 1, 0, 0, 0, 0, 0
145                 /* wbl, vpw, lcdac, wbf */
146 };
147 #endif /* CONFIG_HITACHI_SP19X001_Z1A */
148 /*----------------------------------------------------------------------*/
149
150 /*----------------------------------------------------------------------*/
151 #ifdef CONFIG_NEC_NL6648AC33
152 /*
153  *  NEC NL6648AC33-18. Active, color, single scan.
154  */
155 static vidinfo_t panel_info = {
156     640, 480, 132, 99, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
157     3, 0, 0, 1, 1, 144, 2, 0, 33
158                 /* wbl, vpw, lcdac, wbf */
159 };
160 #endif /* CONFIG_NEC_NL6648AC33 */
161 /*----------------------------------------------------------------------*/
162
163 #ifdef CONFIG_NEC_NL6648BC20
164 /*
165  *  NEC NL6648BC20-08. 6.5", 640x480. Active, color, single scan.
166  */
167 static vidinfo_t panel_info = {
168     640, 480, 132, 99, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
169     3, 0, 0, 1, 1, 144, 2, 0, 33
170                 /* wbl, vpw, lcdac, wbf */
171 };
172 #endif /* CONFIG_NEC_NL6648BC20 */
173 /*----------------------------------------------------------------------*/
174
175 #ifdef CONFIG_SHARP_LQ104V7DS01
176 /*
177  *  SHARP LQ104V7DS01. 6.5", 640x480. Active, color, single scan.
178  */
179 static vidinfo_t panel_info = {
180     640, 480, 132, 99, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_LOW,
181     3, 0, 0, 1, 1, 25, 1, 0, 33
182                 /* wbl, vpw, lcdac, wbf */
183 };
184 #endif /* CONFIG_SHARP_LQ104V7DS01 */
185 /*----------------------------------------------------------------------*/
186
187 #ifdef CONFIG_SHARP_16x9
188 /*
189  * Sharp 320x240. Active, color, single scan.  It isn't 16x9, and I am
190  * not sure what it is.......
191  */
192 static vidinfo_t panel_info = {
193     320, 240, 0, 0, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH,
194     3, 0, 0, 1, 1, 15, 4, 0, 3
195 };
196 #endif /* CONFIG_SHARP_16x9 */
197 /*----------------------------------------------------------------------*/
198
199 #ifdef CONFIG_SHARP_LQ057Q3DC02
200 /*
201  * Sharp LQ057Q3DC02 display. Active, color, single scan.
202  */
203 #define LCD_DF 12
204
205 static vidinfo_t panel_info = {
206     320, 240, 0, 0, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
207     3, 0, 0, 1, 1, 15, 4, 0, 3
208                 /* wbl, vpw, lcdac, wbf */
209 };
210 #define LCD_INFO_BELOW_LOGO
211 #endif /* CONFIG_SHARP_LQ057Q3DC02 */
212 /*----------------------------------------------------------------------*/
213
214 #ifdef CONFIG_SHARP_LQ64D341
215 /*
216  * Sharp LQ64D341 display, 640x480. Active, color, single scan.
217  */
218 static vidinfo_t panel_info = {
219     640, 480, 0, 0, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
220     3, 0, 0, 1, 1, 128, 16, 0, 32
221                 /* wbl, vpw, lcdac, wbf */
222 };
223 #endif /* CONFIG_SHARP_LQ64D341 */
224
225 #ifdef CONFIG_SHARP_LQ084V1DG21
226 /*
227  * Sharp LQ084V1DG21 display, 640x480. Active, color, single scan.
228  */
229 static vidinfo_t panel_info = {
230     640, 480, 171, 129, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_LOW,
231     3, 0, 0, 1, 1, 160, 3, 0, 48
232                 /* wbl, vpw, lcdac, wbf */
233 };
234 #endif /* CONFIG_SHARP_LQ084V1DG21 */
235
236 /*----------------------------------------------------------------------*/
237
238 #ifdef CONFIG_HLD1045
239 /*
240  * HLD1045 display, 640x480. Active, color, single scan.
241  */
242 static vidinfo_t panel_info = {
243     640, 480, 0, 0, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
244     3, 0, 0, 1, 1, 160, 3, 0, 48
245                 /* wbl, vpw, lcdac, wbf */
246 };
247 #endif /* CONFIG_HLD1045 */
248 /*----------------------------------------------------------------------*/
249
250 #ifdef CONFIG_PRIMEVIEW_V16C6448AC
251 /*
252  * Prime View V16C6448AC
253  */
254 static vidinfo_t panel_info = {
255     640, 480, 130, 98, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
256     3, 0, 0, 1, 1, 144, 2, 0, 35
257                 /* wbl, vpw, lcdac, wbf */
258 };
259 #endif /* CONFIG_PRIMEVIEW_V16C6448AC */
260
261 /*----------------------------------------------------------------------*/
262
263 #ifdef CONFIG_OPTREX_BW
264 /*
265  * Optrex   CBL50840-2 NF-FW 99 22 M5
266  * or
267  * Hitachi  LMG6912RPFC-00T
268  * or
269  * Hitachi  SP14Q002
270  *
271  * 320x240. Black & white.
272  */
273 #define OPTREX_BPP      0       /* 0 - monochrome,     1 bpp */
274                                 /* 1 -  4 grey levels, 2 bpp */
275                                 /* 2 - 16 grey levels, 4 bpp */
276 static vidinfo_t panel_info = {
277     320, 240, 0, 0, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_LOW,
278     OPTREX_BPP, 0, 0, 0, 0, 0, 0, 0, 0, 4
279 };
280 #endif /* CONFIG_OPTREX_BW */
281
282 /*-----------------------------------------------------------------*/
283 #ifdef CONFIG_EDT32F10
284 /*
285  * Emerging Display Technologies 320x240. Passive, monochrome, single scan.
286  */
287 #define LCD_BPP         LCD_MONOCHROME
288 #define LCD_DF          10
289
290 static vidinfo_t panel_info = {
291     320, 240, 0, 0, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_LOW,
292     LCD_BPP,  0, 0, 0, 0, 33, 0, 0, 0
293 };
294 #endif
295 /*----------------------------------------------------------------------*/
296
297 #if defined(LCD_INFO_BELOW_LOGO)
298 # define LCD_INFO_X             0
299 # define LCD_INFO_Y             (BMP_LOGO_HEIGHT + VIDEO_FONT_HEIGHT)
300 #elif defined(CONFIG_LCD_LOGO)
301 # define LCD_INFO_X             (BMP_LOGO_WIDTH + 4 * VIDEO_FONT_WIDTH)
302 # define LCD_INFO_Y             (VIDEO_FONT_HEIGHT)
303 #else
304 # define LCD_INFO_X             (VIDEO_FONT_WIDTH)
305 # define LCD_INFO_Y             (VIDEO_FONT_HEIGHT)
306 #endif
307
308 #ifndef LCD_BPP
309 #define LCD_BPP                 LCD_COLOR8
310 #endif
311 #ifndef LCD_DF
312 #define LCD_DF                  1
313 #endif
314
315 #define NBITS(bit_code)         (1 << (bit_code))
316 #define NCOLORS(bit_code)       (1 << NBITS(bit_code))
317
318 static int lcd_line_length;
319
320 static int lcd_color_fg;
321 static int lcd_color_bg;
322
323 char lcd_is_enabled = 0;                /* Indicate that LCD is enabled */
324
325 /*
326  * Frame buffer memory information
327  */
328 static void *lcd_base;                  /* Start of framebuffer memory  */
329 static void *lcd_console_address;       /* Start of console buffer      */
330
331
332 /************************************************************************/
333 /* ** CONSOLE CONSTANTS                                                 */
334 /************************************************************************/
335
336 #if LCD_BPP == LCD_MONOCHROME
337
338 /*
339  * Simple color definitions
340  */
341 #define CONSOLE_COLOR_BLACK      0
342 #define CONSOLE_COLOR_WHITE      1      /* Must remain last / highest */
343
344 #else
345
346 /*
347  * Simple color definitions
348  */
349 #define CONSOLE_COLOR_BLACK      0
350 #define CONSOLE_COLOR_RED        1
351 #define CONSOLE_COLOR_GREEN      2
352 #define CONSOLE_COLOR_YELLOW     3
353 #define CONSOLE_COLOR_BLUE       4
354 #define CONSOLE_COLOR_MAGENTA    5
355 #define CONSOLE_COLOR_CYAN       6
356 #define CONSOLE_COLOR_GREY      14
357 #define CONSOLE_COLOR_WHITE     15      /* Must remain last / highest */
358
359 #endif
360
361 #if defined(CONFIG_LCD_LOGO) && (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET)
362 #error Default Color Map overlaps with Logo Color Map
363 #endif
364
365 /************************************************************************/
366
367 #ifndef PAGE_SIZE
368 #define PAGE_SIZE       4096
369 #endif
370
371
372 /************************************************************************/
373 /* ** CONSOLE DEFINITIONS & FUNCTIONS                                   */
374 /************************************************************************/
375
376 #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
377 #define CONSOLE_ROWS            ((panel_info.vl_row-BMP_LOGO_HEIGHT) \
378                                         / VIDEO_FONT_HEIGHT)
379 #else
380 #define CONSOLE_ROWS            (panel_info.vl_row / VIDEO_FONT_HEIGHT)
381 #endif
382 #define CONSOLE_COLS            (panel_info.vl_col / VIDEO_FONT_WIDTH)
383 #define CONSOLE_ROW_SIZE        (VIDEO_FONT_HEIGHT * lcd_line_length)
384 #define CONSOLE_ROW_FIRST       (lcd_console_address)
385 #define CONSOLE_ROW_SECOND      (lcd_console_address + CONSOLE_ROW_SIZE)
386 #define CONSOLE_ROW_LAST        (lcd_console_address + CONSOLE_SIZE \
387                                         - CONSOLE_ROW_SIZE)
388 #define CONSOLE_SIZE            (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
389 #define CONSOLE_SCROLL_SIZE     (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
390
391 #if  LCD_BPP == LCD_MONOCHROME
392 #define COLOR_MASK(c)           ((c)      | (c) << 1 | (c) << 2 | (c) << 3 | \
393                                  (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7)
394 #elif LCD_BPP == LCD_COLOR8
395 #define COLOR_MASK(c)           (c)
396 #else
397 #error Unsupported LCD BPP.
398 #endif
399
400 static short console_col;
401 static short console_row;
402
403 /************************************************************************/
404
405 ulong   lcd_setmem (ulong addr);
406
407 static void     lcd_drawchars  (ushort x, ushort y, uchar *str, int count);
408 static inline void lcd_puts_xy (ushort x, ushort y, uchar *s);
409 static inline void lcd_putc_xy (ushort x, ushort y, uchar  c);
410
411 int     lcd_init (void *lcdbase);
412
413 static void     lcd_ctrl_init (void *lcdbase);
414 static void     lcd_enable (void);
415 static void    *lcd_logo (void);
416 #if LCD_BPP == LCD_COLOR8
417 static void     lcd_setcolreg (ushort regno,
418                                 ushort red, ushort green, ushort blue);
419 #endif
420 #if LCD_BPP == LCD_MONOCHROME
421 static void     lcd_initcolregs (void);
422 #endif
423 static int      lcd_getbgcolor (void);
424 static void     lcd_setfgcolor (int color);
425 static void     lcd_setbgcolor (int color);
426
427 #if defined(CONFIG_RBC823)
428 void    lcd_disable (void);
429 #endif
430
431 #ifdef  NOT_USED_SO_FAR
432 static void     lcd_getcolreg (ushort regno,
433                                 ushort *red, ushort *green, ushort *blue);
434 static int      lcd_getfgcolor (void);
435 #endif  /* NOT_USED_SO_FAR */
436
437 /************************************************************************/
438
439 /*----------------------------------------------------------------------*/
440
441 static void console_scrollup (void)
442 {
443 #if 1
444         /* Copy up rows ignoring the first one */
445         memcpy (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE);
446
447         /* Clear the last one */
448         memset (CONSOLE_ROW_LAST, COLOR_MASK(lcd_color_bg), CONSOLE_ROW_SIZE);
449 #else
450         /*
451          * Poor attempt to optimize speed by moving "long"s.
452          * But the code is ugly, and not a bit faster :-(
453          */
454         ulong *t = (ulong *)CONSOLE_ROW_FIRST;
455         ulong *s = (ulong *)CONSOLE_ROW_SECOND;
456         ulong    l = CONSOLE_SCROLL_SIZE / sizeof(ulong);
457         uchar  c = lcd_color_bg & 0xFF;
458         ulong val= (c<<24) | (c<<16) | (c<<8) | c;
459
460         while (l--)
461                 *t++ = *s++;
462
463         t = (ulong *)CONSOLE_ROW_LAST;
464         l = CONSOLE_ROW_SIZE / sizeof(ulong);
465
466         while (l-- > 0)
467                 *t++ = val;
468 #endif
469 }
470
471 /*----------------------------------------------------------------------*/
472
473 static inline void console_back (void)
474 {
475         if (--console_col < 0) {
476                 console_col = CONSOLE_COLS-1 ;
477                 if (--console_row < 0) {
478                         console_row = 0;
479                 }
480         }
481
482         lcd_putc_xy (console_col * VIDEO_FONT_WIDTH,
483                      console_row * VIDEO_FONT_HEIGHT,
484                      ' ');
485 }
486
487 /*----------------------------------------------------------------------*/
488
489 static inline void console_newline (void)
490 {
491         ++console_row;
492         console_col = 0;
493
494         /* Check if we need to scroll the terminal */
495         if (console_row >= CONSOLE_ROWS) {
496                 /* Scroll everything up */
497                 console_scrollup () ;
498                 --console_row;
499         }
500 }
501
502 /*----------------------------------------------------------------------*/
503
504 void lcd_putc (const char c)
505 {
506         if (!lcd_is_enabled) {
507                 serial_putc(c);
508                 return;
509         }
510
511         switch (c) {
512         case '\r':      console_col = 0;
513                         return;
514
515         case '\n':      console_newline();
516                         return;
517
518         case '\t':      /* Tab (8 chars alignment) */
519                         console_col |=  8;
520                         console_col &= ~7;
521
522                         if (console_col >= CONSOLE_COLS) {
523                                 console_newline();
524                         }
525                         return;
526
527         case '\b':      console_back();
528                         return;
529
530         default:        lcd_putc_xy (console_col * VIDEO_FONT_WIDTH,
531                                      console_row * VIDEO_FONT_HEIGHT,
532                                      c);
533                         if (++console_col >= CONSOLE_COLS) {
534                                 console_newline();
535                         }
536                         return;
537         }
538         /* NOTREACHED */
539 }
540
541 /*----------------------------------------------------------------------*/
542
543 void lcd_puts (const char *s)
544 {
545         if (!lcd_is_enabled) {
546                 serial_puts (s);
547                 return;
548         }
549
550         while (*s) {
551                 lcd_putc (*s++);
552         }
553 }
554
555 /************************************************************************/
556 /* ** Low-Level Graphics Routines                                       */
557 /************************************************************************/
558
559 static void lcd_drawchars (ushort x, ushort y, uchar *str, int count)
560 {
561         uchar *dest;
562         ushort off, row;
563
564         dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8);
565         off  = x * (1 << LCD_BPP) % 8;
566
567         for (row=0;  row < VIDEO_FONT_HEIGHT;  ++row, dest += lcd_line_length)  {
568                 uchar *s = str;
569                 uchar *d = dest;
570                 int i;
571
572 #if LCD_BPP == LCD_MONOCHROME
573                 uchar rest = *d & -(1 << (8-off));
574                 uchar sym;
575 #endif
576                 for (i=0; i<count; ++i) {
577                         uchar c, bits;
578
579                         c = *s++;
580                         bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
581
582 #if LCD_BPP == LCD_MONOCHROME
583                         sym  = (COLOR_MASK(lcd_color_fg) & bits) |
584                                (COLOR_MASK(lcd_color_bg) & ~bits);
585
586                         *d++ = rest | (sym >> off);
587                         rest = sym << (8-off);
588 #elif LCD_BPP == LCD_COLOR8
589                         for (c=0; c<8; ++c) {
590                                 *d++ = (bits & 0x80) ?
591                                                 lcd_color_fg : lcd_color_bg;
592                                 bits <<= 1;
593                         }
594 #endif
595                 }
596
597 #if LCD_BPP == LCD_MONOCHROME
598                 *d  = rest | (*d & ((1 << (8-off)) - 1));
599 #endif
600         }
601 }
602
603 /*----------------------------------------------------------------------*/
604
605 static inline void lcd_puts_xy (ushort x, ushort y, uchar *s)
606 {
607 #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
608         lcd_drawchars (x, y+BMP_LOGO_HEIGHT, s, strlen (s));
609 #else
610         lcd_drawchars (x, y, s, strlen (s));
611 #endif
612 }
613
614 /*----------------------------------------------------------------------*/
615
616 static inline void lcd_putc_xy (ushort x, ushort y, uchar c)
617 {
618 #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
619         lcd_drawchars (x, y+BMP_LOGO_HEIGHT, &c, 1);
620 #else
621         lcd_drawchars (x, y, &c, 1);
622 #endif
623 }
624
625 /************************************************************************/
626 /**  Small utility to check that you got the colours right              */
627 /************************************************************************/
628 #ifdef LCD_TEST_PATTERN
629
630 #define N_BLK_VERT      2
631 #define N_BLK_HOR       3
632
633 static int test_colors[N_BLK_HOR*N_BLK_VERT] = {
634         CONSOLE_COLOR_RED,      CONSOLE_COLOR_GREEN,    CONSOLE_COLOR_YELLOW,
635         CONSOLE_COLOR_BLUE,     CONSOLE_COLOR_MAGENTA,  CONSOLE_COLOR_CYAN,
636 };
637
638 static void test_pattern (void)
639 {
640         ushort v_max  = panel_info.vl_row;
641         ushort h_max  = panel_info.vl_col;
642         ushort v_step = (v_max + N_BLK_VERT - 1) / N_BLK_VERT;
643         ushort h_step = (h_max + N_BLK_HOR  - 1) / N_BLK_HOR;
644         ushort v, h;
645         uchar *pix = (uchar *)lcd_base;
646
647         printf ("[LCD] Test Pattern: %d x %d [%d x %d]\n",
648                 h_max, v_max, h_step, v_step);
649
650         /* WARNING: Code silently assumes 8bit/pixel */
651         for (v=0; v<v_max; ++v) {
652                 uchar iy = v / v_step;
653                 for (h=0; h<h_max; ++h) {
654                         uchar ix = N_BLK_HOR * iy + (h/h_step);
655                         *pix++ = test_colors[ix];
656                 }
657         }
658 }
659 #endif /* LCD_TEST_PATTERN */
660
661
662 /************************************************************************/
663 /* ** GENERIC Initialization Routines                                   */
664 /************************************************************************/
665
666 int drv_lcd_init (void)
667 {
668         DECLARE_GLOBAL_DATA_PTR;
669
670         device_t lcddev;
671         int rc;
672
673         lcd_base = (void *)(gd->fb_base);
674
675         lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
676
677         lcd_init (lcd_base);            /* LCD initialization */
678
679         /* Device initialization */
680         memset (&lcddev, 0, sizeof (lcddev));
681
682         strcpy (lcddev.name, "lcd");
683         lcddev.ext   = 0;                       /* No extensions */
684         lcddev.flags = DEV_FLAGS_OUTPUT;        /* Output only */
685         lcddev.putc  = lcd_putc;                /* 'putc' function */
686         lcddev.puts  = lcd_puts;                /* 'puts' function */
687
688         rc = device_register (&lcddev);
689
690         return (rc == 0) ? 1 : rc;
691 }
692
693 /*----------------------------------------------------------------------*/
694
695 int lcd_init (void *lcdbase)
696 {
697         /* Initialize the lcd controller */
698         debug ("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
699
700         lcd_ctrl_init (lcdbase);
701
702 #if LCD_BPP == LCD_MONOCHROME
703         /* Setting the palette */
704         lcd_initcolregs();
705
706 #elif LCD_BPP == LCD_COLOR8
707         /* Setting the palette */
708         lcd_setcolreg  (CONSOLE_COLOR_BLACK,       0,    0,    0);
709         lcd_setcolreg  (CONSOLE_COLOR_RED,      0xFF,    0,    0);
710         lcd_setcolreg  (CONSOLE_COLOR_GREEN,       0, 0xFF,    0);
711         lcd_setcolreg  (CONSOLE_COLOR_YELLOW,   0xFF, 0xFF,    0);
712         lcd_setcolreg  (CONSOLE_COLOR_BLUE,        0,    0, 0xFF);
713         lcd_setcolreg  (CONSOLE_COLOR_MAGENTA,  0xFF,    0, 0xFF);
714         lcd_setcolreg  (CONSOLE_COLOR_CYAN,        0, 0xFF, 0xFF);
715         lcd_setcolreg  (CONSOLE_COLOR_GREY,     0xAA, 0xAA, 0xAA);
716         lcd_setcolreg  (CONSOLE_COLOR_WHITE,    0xFF, 0xFF, 0xFF);
717 #endif
718
719 #ifndef CFG_WHITE_ON_BLACK
720         lcd_setfgcolor (CONSOLE_COLOR_BLACK);
721         lcd_setbgcolor (CONSOLE_COLOR_WHITE);
722 #else
723         lcd_setfgcolor (CONSOLE_COLOR_WHITE);
724         lcd_setbgcolor (CONSOLE_COLOR_BLACK);
725 #endif  /* CFG_WHITE_ON_BLACK */
726
727 #ifdef  LCD_TEST_PATTERN
728         test_pattern();
729 #else
730         /* set framebuffer to background color */
731         memset ((char *)lcd_base,
732                 COLOR_MASK(lcd_getbgcolor()),
733                 lcd_line_length*panel_info.vl_row);
734 #endif
735
736         lcd_enable ();
737
738         /* Paint the logo and retrieve LCD base address */
739         debug ("[LCD] Drawing the logo...\n");
740         lcd_console_address = lcd_logo ();
741
742         /* Initialize the console */
743         console_col = 0;
744 #ifdef LCD_INFO_BELOW_LOGO
745         console_row = 7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT;
746 #else
747         console_row = 1;        /* leave 1 blank line below logo */
748 #endif
749         lcd_is_enabled = 1;
750
751         return 0;
752 }
753
754
755 /************************************************************************/
756 /* ** ROM capable initialization part - needed to reserve FB memory     */
757 /************************************************************************/
758
759 /*
760  * This is called early in the system initialization to grab memory
761  * for the LCD controller.
762  * Returns new address for monitor, after reserving LCD buffer memory
763  *
764  * Note that this is running from ROM, so no write access to global data.
765  */
766 ulong lcd_setmem (ulong addr)
767 {
768         ulong size;
769         int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
770
771         debug ("LCD panel info: %d x %d, %d bit/pix\n",
772                 panel_info.vl_col, panel_info.vl_row, NBITS (panel_info.vl_bpix) );
773
774         size = line_length * panel_info.vl_row;
775
776         /* Round up to nearest full page */
777         size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
778
779         /* Allocate pages for the frame buffer. */
780         addr -= size;
781
782         debug ("Reserving %ldk for LCD Framebuffer at: %08lx\n", size>>10, addr);
783
784         return (addr);
785 }
786
787
788 /************************************************************************/
789 /* ----------------- chipset specific functions ----------------------- */
790 /************************************************************************/
791
792 static void lcd_ctrl_init (void *lcdbase)
793 {
794         volatile immap_t *immr = (immap_t *) CFG_IMMR;
795         volatile lcd823_t *lcdp = &immr->im_lcd;
796
797         uint lccrtmp;
798         uint lchcr_hpc_tmp;
799
800         /* Initialize the LCD control register according to the LCD
801          * parameters defined.  We do everything here but enable
802          * the controller.
803          */
804
805         lccrtmp  = LCDBIT (LCCR_BNUM_BIT,
806                    (((panel_info.vl_row * panel_info.vl_col) * (1 << LCD_BPP)) / 128));
807
808         lccrtmp |= LCDBIT (LCCR_CLKP_BIT, panel_info.vl_clkp)   |
809                    LCDBIT (LCCR_OEP_BIT,  panel_info.vl_oep)    |
810                    LCDBIT (LCCR_HSP_BIT,  panel_info.vl_hsp)    |
811                    LCDBIT (LCCR_VSP_BIT,  panel_info.vl_vsp)    |
812                    LCDBIT (LCCR_DP_BIT,   panel_info.vl_dp)     |
813                    LCDBIT (LCCR_BPIX_BIT, panel_info.vl_bpix)   |
814                    LCDBIT (LCCR_LBW_BIT,  panel_info.vl_lbw)    |
815                    LCDBIT (LCCR_SPLT_BIT, panel_info.vl_splt)   |
816                    LCDBIT (LCCR_CLOR_BIT, panel_info.vl_clor)   |
817                    LCDBIT (LCCR_TFT_BIT,  panel_info.vl_tft);
818
819 #if 0
820         lccrtmp |= ((SIU_LEVEL5 / 2) << 12);
821         lccrtmp |= LCCR_EIEN;
822 #endif
823
824         lcdp->lcd_lccr = lccrtmp;
825         lcdp->lcd_lcsr = 0xFF;          /* Clear pending interrupts */
826
827         /* Initialize LCD controller bus priorities.
828          */
829 #ifdef CONFIG_RBC823
830         immr->im_siu_conf.sc_sdcr = (immr->im_siu_conf.sc_sdcr & ~0x0f) | 1;    /* RAID = 01, LAID = 00 */
831 #else
832         immr->im_siu_conf.sc_sdcr &= ~0x0f;     /* RAID = LAID = 0 */
833
834         /* set SHFT/CLOCK division factor 4
835          * This needs to be set based upon display type and processor
836          * speed.  The TFT displays run about 20 to 30 MHz.
837          * I was running 64 MHz processor speed.
838          * The value for this divider must be chosen so the result is
839          * an integer of the processor speed (i.e., divide by 3 with
840          * 64 MHz would be bad).
841          */
842         immr->im_clkrst.car_sccr &= ~0x1F;
843         immr->im_clkrst.car_sccr |= LCD_DF;     /* was 8 */
844
845 #endif /* CONFIG_RBC823 */
846
847 #if defined(CONFIG_RBC823)
848         /* Enable LCD on port D.
849          */
850         immr->im_ioport.iop_pddat &= 0x0300;
851         immr->im_ioport.iop_pdpar |= 0x1CFF;
852         immr->im_ioport.iop_pddir |= 0x1CFF;
853
854         /* Configure LCD_ON, VEE_ON, CCFL_ON on port B.
855          */
856         immr->im_cpm.cp_pbdat &= ~0x00005001;
857         immr->im_cpm.cp_pbpar &= ~0x00005001;
858         immr->im_cpm.cp_pbdir |=  0x00005001;
859 #elif !defined(CONFIG_EDT32F10)
860         /* Enable LCD on port D.
861          */
862         immr->im_ioport.iop_pdpar |= 0x1FFF;
863         immr->im_ioport.iop_pddir |= 0x1FFF;
864
865         /* Enable LCD_A/B/C on port B.
866          */
867         immr->im_cpm.cp_pbpar |= 0x00005001;
868         immr->im_cpm.cp_pbdir |= 0x00005001;
869 #else
870         /* Enable LCD on port D.
871          */
872         immr->im_ioport.iop_pdpar |= 0x1DFF;
873         immr->im_ioport.iop_pdpar &= ~0x0200;
874         immr->im_ioport.iop_pddir |= 0x1FFF;
875         immr->im_ioport.iop_pddat |= 0x0200;
876 #endif
877
878         /* Load the physical address of the linear frame buffer
879          * into the LCD controller.
880          * BIG NOTE:  This has to be modified to load A and B depending
881          * upon the split mode of the LCD.
882          */
883         lcdp->lcd_lcfaa = (ulong)lcd_base;
884         lcdp->lcd_lcfba = (ulong)lcd_base;
885
886         /* MORE HACKS...This must be updated according to 823 manual
887          * for different panels.
888          * Udi Finkelstein - done - see below:
889          * Note: You better not try unsupported combinations such as
890          * 4-bit wide passive dual scan LCD at 4/8 Bit color.
891          */
892         lchcr_hpc_tmp =
893                 (panel_info.vl_col *
894                  (panel_info.vl_tft ? 8 :
895                         (((2 - panel_info.vl_lbw) << /* 4 bit=2, 8-bit = 1 */
896                          /* use << to mult by: single scan = 1, dual scan = 2 */
897                           panel_info.vl_splt) *
898                          (panel_info.vl_bpix | 1)))) >> 3; /* 2/4 BPP = 1, 8/16 BPP = 3 */
899
900         lcdp->lcd_lchcr = LCHCR_BO |
901                           LCDBIT (LCHCR_AT_BIT, 4) |
902                           LCDBIT (LCHCR_HPC_BIT, lchcr_hpc_tmp) |
903                           panel_info.vl_wbl;
904
905         lcdp->lcd_lcvcr = LCDBIT (LCVCR_VPW_BIT, panel_info.vl_vpw) |
906                           LCDBIT (LCVCR_LCD_AC_BIT, panel_info.vl_lcdac) |
907                           LCDBIT (LCVCR_VPC_BIT, panel_info.vl_row) |
908                           panel_info.vl_wbf;
909
910 }
911
912 /*----------------------------------------------------------------------*/
913
914 #ifdef  NOT_USED_SO_FAR
915 static void
916 lcd_getcolreg (ushort regno, ushort *red, ushort *green, ushort *blue)
917 {
918         volatile immap_t *immr = (immap_t *) CFG_IMMR;
919         volatile cpm8xx_t *cp = &(immr->im_cpm);
920         unsigned short colreg, *cmap_ptr;
921
922         cmap_ptr = (unsigned short *)&cp->lcd_cmap[regno * 2];
923
924         colreg = *cmap_ptr;
925 #ifdef  CFG_INVERT_COLORS
926         colreg ^= 0x0FFF;
927 #endif
928
929         *red   = (colreg >> 8) & 0x0F;
930         *green = (colreg >> 4) & 0x0F;
931         *blue  =  colreg       & 0x0F;
932 }
933 #endif  /* NOT_USED_SO_FAR */
934
935 /*----------------------------------------------------------------------*/
936
937 #if LCD_BPP == LCD_COLOR8
938 static void
939 lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
940 {
941         volatile immap_t *immr = (immap_t *) CFG_IMMR;
942         volatile cpm8xx_t *cp = &(immr->im_cpm);
943         unsigned short colreg, *cmap_ptr;
944
945         cmap_ptr = (unsigned short *)&cp->lcd_cmap[regno * 2];
946
947         colreg = ((red   & 0x0F) << 8) |
948                  ((green & 0x0F) << 4) |
949                   (blue  & 0x0F) ;
950 #ifdef  CFG_INVERT_COLORS
951         colreg ^= 0x0FFF;
952 #endif
953         *cmap_ptr = colreg;
954
955         debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %02X%02X\n",
956                 regno, &(cp->lcd_cmap[regno * 2]),
957                 red, green, blue,
958                 cp->lcd_cmap[ regno * 2 ], cp->lcd_cmap[(regno * 2) + 1]);
959 }
960 #endif  /* LCD_COLOR8 */
961
962 /*----------------------------------------------------------------------*/
963
964 #if LCD_BPP == LCD_MONOCHROME
965 static
966 void lcd_initcolregs (void)
967 {
968         volatile immap_t *immr = (immap_t *) CFG_IMMR;
969         volatile cpm8xx_t *cp = &(immr->im_cpm);
970         ushort regno;
971
972         for (regno = 0; regno < 16; regno++) {
973                 cp->lcd_cmap[regno * 2] = 0;
974                 cp->lcd_cmap[(regno * 2) + 1] = regno & 0x0f;
975         }
976 }
977 #endif
978
979 /*----------------------------------------------------------------------*/
980
981 static void lcd_setfgcolor (int color)
982 {
983         lcd_color_fg = color & 0x0F;
984 }
985
986 /*----------------------------------------------------------------------*/
987
988 static void lcd_setbgcolor (int color)
989 {
990         lcd_color_bg = color & 0x0F;
991 }
992
993 /*----------------------------------------------------------------------*/
994
995 #ifdef  NOT_USED_SO_FAR
996 static int lcd_getfgcolor (void)
997 {
998         return lcd_color_fg;
999 }
1000 #endif  /* NOT_USED_SO_FAR */
1001
1002 /*----------------------------------------------------------------------*/
1003
1004 static int lcd_getbgcolor (void)
1005 {
1006         return lcd_color_bg;
1007 }
1008
1009 /*----------------------------------------------------------------------*/
1010
1011 static void lcd_enable (void)
1012 {
1013         volatile immap_t *immr = (immap_t *) CFG_IMMR;
1014         volatile lcd823_t *lcdp = &immr->im_lcd;
1015
1016         /* Enable the LCD panel */
1017 #ifndef CONFIG_RBC823
1018         immr->im_siu_conf.sc_sdcr |= (1 << (31 - 25));          /* LAM = 1 */
1019 #endif
1020         lcdp->lcd_lccr |= LCCR_PON;
1021
1022 #ifdef CONFIG_V37
1023         /* Turn on display backlight */
1024         immr->im_cpm.cp_pbpar |= 0x00008000;
1025         immr->im_cpm.cp_pbdir |= 0x00008000;
1026 #elif defined(CONFIG_RBC823)
1027         /* Turn on display backlight */
1028         immr->im_cpm.cp_pbdat |= 0x00004000;
1029 #endif
1030
1031 #if defined(CONFIG_LWMON)
1032     {   uchar c = pic_read (0x60);
1033 #if defined(CONFIG_LCD) && defined(CONFIG_LWMON) && (CONFIG_POST & CFG_POST_SYSMON)
1034         c |= 0x04;      /* Chip Enable LCD */
1035 #else
1036         c |= 0x07;      /* Power on CCFL, Enable CCFL, Chip Enable LCD */
1037 #endif
1038         pic_write (0x60, c);
1039     }
1040 #endif /* CONFIG_LWMON */
1041
1042 #if defined(CONFIG_R360MPI)
1043     {
1044         extern void r360_i2c_lcd_write (uchar data0, uchar data1);
1045
1046         r360_i2c_lcd_write(0x10, 0x01);
1047         r360_i2c_lcd_write(0x20, 0x01);
1048         r360_i2c_lcd_write(0x3F, 0xFF);
1049         r360_i2c_lcd_write(0x47, 0xFF);
1050     }
1051 #endif /* CONFIG_R360MPI */
1052 #ifdef CONFIG_RBC823
1053         udelay(200000); /* wait 200ms */
1054         /* Turn VEE_ON first */
1055         immr->im_cpm.cp_pbdat |= 0x00000001;
1056         udelay(200000); /* wait 200ms */
1057         /* Now turn on LCD_ON */
1058         immr->im_cpm.cp_pbdat |= 0x00001000;
1059 #endif
1060 }
1061
1062 /*----------------------------------------------------------------------*/
1063
1064 #if defined (CONFIG_RBC823)
1065 void lcd_disable (void)
1066 {
1067         volatile immap_t *immr = (immap_t *) CFG_IMMR;
1068         volatile lcd823_t *lcdp = &immr->im_lcd;
1069
1070 #if defined(CONFIG_LWMON)
1071     {   uchar c = pic_read (0x60);
1072         c &= ~0x07;     /* Power off CCFL, Disable CCFL, Chip Disable LCD */
1073         pic_write (0x60, c);
1074     }
1075 #elif defined(CONFIG_R360MPI)
1076     {
1077         extern void r360_i2c_lcd_write (uchar data0, uchar data1);
1078
1079         r360_i2c_lcd_write(0x10, 0x00);
1080         r360_i2c_lcd_write(0x20, 0x00);
1081         r360_i2c_lcd_write(0x30, 0x00);
1082         r360_i2c_lcd_write(0x40, 0x00);
1083     }
1084 #endif /* CONFIG_LWMON */
1085         /* Disable the LCD panel */
1086         lcdp->lcd_lccr &= ~LCCR_PON;
1087 #ifdef CONFIG_RBC823
1088         /* Turn off display backlight, VEE and LCD_ON */
1089         immr->im_cpm.cp_pbdat &= ~0x00005001;
1090 #else
1091         immr->im_siu_conf.sc_sdcr &= ~(1 << (31 - 25)); /* LAM = 0 */
1092 #endif /* CONFIG_RBC823 */
1093 }
1094 #endif  /* NOT_USED_SO_FAR || CONFIG_RBC823 */
1095
1096
1097 /************************************************************************/
1098 /* ** Chipset depending Bitmap / Logo stuff...                          */
1099 /************************************************************************/
1100
1101
1102 #ifdef CONFIG_LCD_LOGO
1103 static void bitmap_plot (int x, int y)
1104 {
1105         volatile immap_t *immr = (immap_t *) CFG_IMMR;
1106         volatile cpm8xx_t *cp = &(immr->im_cpm);
1107         ushort *cmap;
1108         ushort i;
1109         uchar *bmap;
1110         uchar *fb;
1111
1112         debug ("Logo: width %d  height %d  colors %d  cmap %d\n",
1113                 BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS,
1114                 sizeof(bmp_logo_palette)/(sizeof(ushort))
1115         );
1116
1117         /* Leave room for default color map */
1118         cmap = (ushort *)&(cp->lcd_cmap[BMP_LOGO_OFFSET*sizeof(ushort)]);
1119
1120         WATCHDOG_RESET();
1121
1122         /* Set color map */
1123         for (i=0; i<(sizeof(bmp_logo_palette)/(sizeof(ushort))); ++i) {
1124                 ushort colreg = bmp_logo_palette[i];
1125 #ifdef  CFG_INVERT_COLORS
1126                 colreg ^= 0xFFF;
1127 #endif
1128                 *cmap++ = colreg;
1129         }
1130
1131         bmap = &bmp_logo_bitmap[0];
1132         fb   = (char *)(lcd_base + y * lcd_line_length + x);
1133
1134         WATCHDOG_RESET();
1135
1136         for (i=0; i<BMP_LOGO_HEIGHT; ++i) {
1137                 memcpy (fb, bmap, BMP_LOGO_WIDTH);
1138                 bmap += BMP_LOGO_WIDTH;
1139                 fb   += panel_info.vl_col;
1140         }
1141
1142         WATCHDOG_RESET();
1143 }
1144 #endif /* CONFIG_LCD_LOGO */
1145
1146 #if (CONFIG_COMMANDS & CFG_CMD_BMP)
1147 /*
1148  * Display the BMP file located at address bmp_image.
1149  * Only uncompressed
1150  */
1151 int lcd_display_bitmap(ulong bmp_image)
1152 {
1153         volatile immap_t *immr = (immap_t *) CFG_IMMR;
1154         volatile cpm8xx_t *cp = &(immr->im_cpm);
1155         ushort *cmap;
1156         ushort i, j;
1157         uchar *fb;
1158         bmp_image_t *bmp=(bmp_image_t *)bmp_image;
1159         uchar *bmap;
1160         ushort padded_line;
1161         unsigned long width, height;
1162         unsigned colors,bpix;
1163         unsigned long compression;
1164
1165         WATCHDOG_RESET();
1166
1167         if (!((bmp->header.signature[0]=='B') &&
1168               (bmp->header.signature[1]=='M'))) {
1169                 printf ("Error: no valid bmp image at %lx\n", bmp_image);
1170                 return 1;
1171         }
1172
1173         width = le32_to_cpu (bmp->header.width);
1174         height = le32_to_cpu (bmp->header.height);
1175         colors = 1<<le16_to_cpu (bmp->header.bit_count);
1176         compression = le32_to_cpu (bmp->header.compression);
1177
1178         bpix = NBITS(panel_info.vl_bpix);
1179
1180         if ((bpix != 1) && (bpix != 8)) {
1181                 printf ("Error: %d bit/pixel mode not supported by U-Boot\n",
1182                         bpix);
1183                 return 1;
1184         }
1185
1186         if (bpix != le16_to_cpu(bmp->header.bit_count)) {
1187                 printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
1188                         bpix,
1189                         le16_to_cpu(bmp->header.bit_count));
1190                 return 1;
1191         }
1192
1193         if (compression!=BMP_BI_RGB) {
1194                 printf ("Error: compression type %ld not supported\n",
1195                         compression);
1196                 return 1;
1197         }
1198
1199         debug ("Display-bmp: %d x %d  with %d colors\n",
1200                width, height, colors);
1201
1202         if (bpix==8) {
1203                 /* Fill the entire color map */
1204                 cmap = (ushort *)&(cp->lcd_cmap[255*sizeof(ushort)]);
1205
1206                 /* Set color map */
1207                 for (i = 0; i < colors; ++i) {
1208                         bmp_color_table_entry_t cte = bmp->color_table[i];
1209                         ushort colreg =
1210                                 ((cte.red>>4)   << 8) |
1211                                 ((cte.green>>4) << 4) |
1212                                 (cte.blue>>4) ;
1213 #ifdef  CFG_INVERT_COLORS
1214                         colreg ^= 0xFFF;
1215 #endif
1216                         *cmap-- = colreg;
1217                 }
1218
1219                 WATCHDOG_RESET();
1220         }
1221
1222         padded_line = (width&0x3) ? ((width&~0x3)+4) : (width);
1223         if (width>panel_info.vl_col)
1224                 width = panel_info.vl_col;
1225         if (height>panel_info.vl_row)
1226                 height = panel_info.vl_row;
1227
1228         bmap = (uchar *)bmp + le32_to_cpu (bmp->header.data_offset);
1229         fb   = (uchar *)
1230                 (lcd_base +
1231                  (((height>=panel_info.vl_row) ? panel_info.vl_row : height)-1)
1232                  * lcd_line_length);
1233         for (i = 0; i < height; ++i) {
1234                 WATCHDOG_RESET();
1235                 for (j = 0; j < width ; j++)
1236                         *(fb++)=255-*(bmap++);
1237                 bmap += (width - padded_line);
1238                 fb   -= (width + lcd_line_length);
1239         }
1240
1241         return (0);
1242 }
1243 #endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) */
1244
1245 /*----------------------------------------------------------------------*/
1246
1247 static void *lcd_logo (void)
1248 {
1249 #ifdef LCD_INFO
1250         DECLARE_GLOBAL_DATA_PTR;
1251
1252         char info[80];
1253         char temp[32];
1254 #endif /* LCD_INFO */
1255
1256 #ifdef CONFIG_SPLASH_SCREEN
1257         char *s;
1258         ulong addr;
1259
1260         if ((s = getenv("splashimage")) != NULL) {
1261                 addr = simple_strtoul(s, NULL, 16);
1262
1263                 if (lcd_display_bitmap (addr) == 0) {
1264                         return ((void *)lcd_base);
1265                 }
1266         }
1267 #endif  /* CONFIG_SPLASH_SCREEN */
1268
1269 #ifdef CONFIG_LCD_LOGO
1270         bitmap_plot (0, 0);
1271 #endif /* CONFIG_LCD_LOGO */
1272
1273
1274 #ifdef LCD_INFO
1275         sprintf (info, "%s (%s - %s) ", U_BOOT_VERSION, __DATE__, __TIME__);
1276         lcd_drawchars (LCD_INFO_X, LCD_INFO_Y, info, strlen(info));
1277
1278         sprintf (info, "(C) 2003 DENX Software Engineering");
1279         lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT,
1280                                         info, strlen(info));
1281
1282         sprintf (info, "    Wolfgang DENK, wd@denx.de");
1283         lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 2,
1284                                         info, strlen(info));
1285 #ifdef LCD_INFO_BELOW_LOGO
1286         sprintf (info, "MPC823 CPU at %s MHz",
1287                 strmhz(temp, gd->cpu_clk));
1288         lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 3,
1289                                         info, strlen(info));
1290         sprintf (info, "  %ld MB RAM, %ld MB Flash",
1291                 gd->ram_size >> 20,
1292                 gd->bd->bi_flashsize >> 20 );
1293         lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4,
1294                                         info, strlen(info));
1295 #else
1296         /* leave one blank line */
1297
1298         sprintf (info, "MPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash",
1299                 strmhz(temp, gd->cpu_clk),
1300                 gd->ram_size >> 20,
1301                 gd->bd->bi_flashsize >> 20 );
1302         lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4,
1303                                         info, strlen(info));
1304 #endif /* LCD_INFO_BELOW_LOGO */
1305 #endif /* LCD_INFO */
1306
1307 #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
1308         return ((void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length));
1309 #else
1310         return ((void *)lcd_base);
1311 #endif  /* CONFIG_LCD_LOGO */
1312 }
1313
1314 /************************************************************************/
1315 /************************************************************************/
1316
1317 #endif /* CONFIG_LCD */