2 * (C) Copyright 2001-2002
3 * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 /************************************************************************/
26 /************************************************************************/
34 #include <linux/types.h>
36 #if defined(CONFIG_POST)
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 */
49 #if defined(CONFIG_V37) || defined(CONFIG_EDT32F10)
50 #undef CONFIG_LCD_LOGO
54 /* #define LCD_TEST_PATTERN */ /* color backgnd for frame/color adjust */
55 /* #define CFG_INVERT_COLORS */ /* Not needed - adjust vl_dp instead */
56 /************************************************************************/
58 /************************************************************************/
59 /* ** BITMAP DISPLAY SUPPORT -- should probably be moved elsewhere */
60 /************************************************************************/
62 #if (CONFIG_COMMANDS & CFG_CMD_BMP)
63 #include <bmp_layout.h>
64 #endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) */
66 /************************************************************************/
67 /* ** FONT AND LOGO DATA */
68 /************************************************************************/
70 #include <video_font.h> /* Get font data, width and height */
72 #ifdef CONFIG_LCD_LOGO
73 # include <bmp_logo.h> /* Get logo data, width and height */
76 /************************************************************************/
77 /************************************************************************/
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.
84 #define CFG_HIGH 0 /* Pins are active high */
85 #define CFG_LOW 1 /* Pins are active low */
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 */
93 /* LCD configuration register.
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 */
106 /* Horizontal control register. Timing from data sheet.
108 ushort vl_wbl
; /* Wait between lines */
110 /* Vertical control register.
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 */
117 #define LCD_MONOCHROME 0
122 /*----------------------------------------------------------------------*/
123 #ifdef CONFIG_KYOCERA_KCS057QV1AJ
125 * Kyocera KCS057QV1AJ-G23. Passive, color, single scan.
127 #define LCD_BPP LCD_COLOR4
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 */
134 #endif /* CONFIG_KYOCERA_KCS057QV1AJ */
135 /*----------------------------------------------------------------------*/
137 /*----------------------------------------------------------------------*/
138 #ifdef CONFIG_HITACHI_SP19X001_Z1A
140 * Hitachi SP19X001-. Active, color, single scan.
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 */
147 #endif /* CONFIG_HITACHI_SP19X001_Z1A */
148 /*----------------------------------------------------------------------*/
150 /*----------------------------------------------------------------------*/
151 #ifdef CONFIG_NEC_NL6648AC33
153 * NEC NL6648AC33-18. Active, color, single scan.
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 */
160 #endif /* CONFIG_NEC_NL6648AC33 */
161 /*----------------------------------------------------------------------*/
163 #ifdef CONFIG_NEC_NL6648BC20
165 * NEC NL6648BC20-08. 6.5", 640x480. Active, color, single scan.
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 */
172 #endif /* CONFIG_NEC_NL6648BC20 */
173 /*----------------------------------------------------------------------*/
175 #ifdef CONFIG_SHARP_LQ104V7DS01
177 * SHARP LQ104V7DS01. 6.5", 640x480. Active, color, single scan.
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 */
184 #endif /* CONFIG_SHARP_LQ104V7DS01 */
185 /*----------------------------------------------------------------------*/
187 #ifdef CONFIG_SHARP_16x9
189 * Sharp 320x240. Active, color, single scan. It isn't 16x9, and I am
190 * not sure what it is.......
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
196 #endif /* CONFIG_SHARP_16x9 */
197 /*----------------------------------------------------------------------*/
199 #ifdef CONFIG_SHARP_LQ057Q3DC02
201 * Sharp LQ057Q3DC02 display. Active, color, single scan.
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 */
210 #define LCD_INFO_BELOW_LOGO
211 #endif /* CONFIG_SHARP_LQ057Q3DC02 */
212 /*----------------------------------------------------------------------*/
214 #ifdef CONFIG_SHARP_LQ64D341
216 * Sharp LQ64D341 display, 640x480. Active, color, single scan.
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 */
223 #endif /* CONFIG_SHARP_LQ64D341 */
225 #ifdef CONFIG_SHARP_LQ084V1DG21
227 * Sharp LQ084V1DG21 display, 640x480. Active, color, single scan.
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 */
234 #endif /* CONFIG_SHARP_LQ084V1DG21 */
236 /*----------------------------------------------------------------------*/
238 #ifdef CONFIG_HLD1045
240 * HLD1045 display, 640x480. Active, color, single scan.
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 */
247 #endif /* CONFIG_HLD1045 */
248 /*----------------------------------------------------------------------*/
250 #ifdef CONFIG_PRIMEVIEW_V16C6448AC
252 * Prime View V16C6448AC
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 */
259 #endif /* CONFIG_PRIMEVIEW_V16C6448AC */
261 /*----------------------------------------------------------------------*/
263 #ifdef CONFIG_OPTREX_BW
265 * Optrex CBL50840-2 NF-FW 99 22 M5
267 * Hitachi LMG6912RPFC-00T
271 * 320x240. Black & white.
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
280 #endif /* CONFIG_OPTREX_BW */
282 /*-----------------------------------------------------------------*/
283 #ifdef CONFIG_EDT32F10
285 * Emerging Display Technologies 320x240. Passive, monochrome, single scan.
287 #define LCD_BPP LCD_MONOCHROME
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
295 /*----------------------------------------------------------------------*/
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)
304 # define LCD_INFO_X (VIDEO_FONT_WIDTH)
305 # define LCD_INFO_Y (VIDEO_FONT_HEIGHT)
309 #define LCD_BPP LCD_COLOR8
315 #define NBITS(bit_code) (1 << (bit_code))
316 #define NCOLORS(bit_code) (1 << NBITS(bit_code))
318 static int lcd_line_length
;
320 static int lcd_color_fg
;
321 static int lcd_color_bg
;
323 char lcd_is_enabled
= 0; /* Indicate that LCD is enabled */
326 * Frame buffer memory information
328 static void *lcd_base
; /* Start of framebuffer memory */
329 static void *lcd_console_address
; /* Start of console buffer */
332 /************************************************************************/
333 /* ** CONSOLE CONSTANTS */
334 /************************************************************************/
336 #if LCD_BPP == LCD_MONOCHROME
339 * Simple color definitions
341 #define CONSOLE_COLOR_BLACK 0
342 #define CONSOLE_COLOR_WHITE 1 /* Must remain last / highest */
347 * Simple color definitions
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 */
361 #if defined(CONFIG_LCD_LOGO) && (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET)
362 #error Default Color Map overlaps with Logo Color Map
365 /************************************************************************/
368 #define PAGE_SIZE 4096
372 /************************************************************************/
373 /* ** CONSOLE DEFINITIONS & FUNCTIONS */
374 /************************************************************************/
376 #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
377 #define CONSOLE_ROWS ((panel_info.vl_row-BMP_LOGO_HEIGHT) \
380 #define CONSOLE_ROWS (panel_info.vl_row / VIDEO_FONT_HEIGHT)
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 \
388 #define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
389 #define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
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)
397 #error Unsupported LCD BPP.
400 static short console_col
;
401 static short console_row
;
403 /************************************************************************/
405 ulong
lcd_setmem (ulong addr
);
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
);
411 int lcd_init (void *lcdbase
);
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
);
420 #if LCD_BPP == LCD_MONOCHROME
421 static void lcd_initcolregs (void);
423 static int lcd_getbgcolor (void);
424 static void lcd_setfgcolor (int color
);
425 static void lcd_setbgcolor (int color
);
427 #if defined(CONFIG_RBC823)
428 void lcd_disable (void);
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 */
437 /************************************************************************/
439 /*----------------------------------------------------------------------*/
441 static void console_scrollup (void)
444 /* Copy up rows ignoring the first one */
445 memcpy (CONSOLE_ROW_FIRST
, CONSOLE_ROW_SECOND
, CONSOLE_SCROLL_SIZE
);
447 /* Clear the last one */
448 memset (CONSOLE_ROW_LAST
, COLOR_MASK(lcd_color_bg
), CONSOLE_ROW_SIZE
);
451 * Poor attempt to optimize speed by moving "long"s.
452 * But the code is ugly, and not a bit faster :-(
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
;
463 t
= (ulong
*)CONSOLE_ROW_LAST
;
464 l
= CONSOLE_ROW_SIZE
/ sizeof(ulong
);
471 /*----------------------------------------------------------------------*/
473 static inline void console_back (void)
475 if (--console_col
< 0) {
476 console_col
= CONSOLE_COLS
-1 ;
477 if (--console_row
< 0) {
482 lcd_putc_xy (console_col
* VIDEO_FONT_WIDTH
,
483 console_row
* VIDEO_FONT_HEIGHT
,
487 /*----------------------------------------------------------------------*/
489 static inline void console_newline (void)
494 /* Check if we need to scroll the terminal */
495 if (console_row
>= CONSOLE_ROWS
) {
496 /* Scroll everything up */
497 console_scrollup () ;
502 /*----------------------------------------------------------------------*/
504 void lcd_putc (const char c
)
506 if (!lcd_is_enabled
) {
512 case '\r': console_col
= 0;
515 case '\n': console_newline();
518 case '\t': /* Tab (8 chars alignment) */
522 if (console_col
>= CONSOLE_COLS
) {
527 case '\b': console_back();
530 default: lcd_putc_xy (console_col
* VIDEO_FONT_WIDTH
,
531 console_row
* VIDEO_FONT_HEIGHT
,
533 if (++console_col
>= CONSOLE_COLS
) {
541 /*----------------------------------------------------------------------*/
543 void lcd_puts (const char *s
)
545 if (!lcd_is_enabled
) {
555 /************************************************************************/
556 /* ** Low-Level Graphics Routines */
557 /************************************************************************/
559 static void lcd_drawchars (ushort x
, ushort y
, uchar
*str
, int count
)
564 dest
= (uchar
*)(lcd_base
+ y
* lcd_line_length
+ x
* (1 << LCD_BPP
) / 8);
565 off
= x
* (1 << LCD_BPP
) % 8;
567 for (row
=0; row
< VIDEO_FONT_HEIGHT
; ++row
, dest
+= lcd_line_length
) {
572 #if LCD_BPP == LCD_MONOCHROME
573 uchar rest
= *d
& -(1 << (8-off
));
576 for (i
=0; i
<count
; ++i
) {
580 bits
= video_fontdata
[c
* VIDEO_FONT_HEIGHT
+ row
];
582 #if LCD_BPP == LCD_MONOCHROME
583 sym
= (COLOR_MASK(lcd_color_fg
) & bits
) |
584 (COLOR_MASK(lcd_color_bg
) & ~bits
);
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
;
597 #if LCD_BPP == LCD_MONOCHROME
598 *d
= rest
| (*d
& ((1 << (8-off
)) - 1));
603 /*----------------------------------------------------------------------*/
605 static inline void lcd_puts_xy (ushort x
, ushort y
, uchar
*s
)
607 #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
608 lcd_drawchars (x
, y
+BMP_LOGO_HEIGHT
, s
, strlen (s
));
610 lcd_drawchars (x
, y
, s
, strlen (s
));
614 /*----------------------------------------------------------------------*/
616 static inline void lcd_putc_xy (ushort x
, ushort y
, uchar c
)
618 #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
619 lcd_drawchars (x
, y
+BMP_LOGO_HEIGHT
, &c
, 1);
621 lcd_drawchars (x
, y
, &c
, 1);
625 /************************************************************************/
626 /** Small utility to check that you got the colours right */
627 /************************************************************************/
628 #ifdef LCD_TEST_PATTERN
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
,
638 static void test_pattern (void)
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
;
645 uchar
*pix
= (uchar
*)lcd_base
;
647 printf ("[LCD] Test Pattern: %d x %d [%d x %d]\n",
648 h_max
, v_max
, h_step
, v_step
);
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
];
659 #endif /* LCD_TEST_PATTERN */
662 /************************************************************************/
663 /* ** GENERIC Initialization Routines */
664 /************************************************************************/
666 int drv_lcd_init (void)
668 DECLARE_GLOBAL_DATA_PTR
;
673 lcd_base
= (void *)(gd
->fb_base
);
675 lcd_line_length
= (panel_info
.vl_col
* NBITS (panel_info
.vl_bpix
)) / 8;
677 lcd_init (lcd_base
); /* LCD initialization */
679 /* Device initialization */
680 memset (&lcddev
, 0, sizeof (lcddev
));
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 */
688 rc
= device_register (&lcddev
);
690 return (rc
== 0) ? 1 : rc
;
693 /*----------------------------------------------------------------------*/
695 int lcd_init (void *lcdbase
)
697 /* Initialize the lcd controller */
698 debug ("[LCD] Initializing LCD frambuffer at %p\n", lcdbase
);
700 lcd_ctrl_init (lcdbase
);
702 #if LCD_BPP == LCD_MONOCHROME
703 /* Setting the palette */
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);
719 #ifndef CFG_WHITE_ON_BLACK
720 lcd_setfgcolor (CONSOLE_COLOR_BLACK
);
721 lcd_setbgcolor (CONSOLE_COLOR_WHITE
);
723 lcd_setfgcolor (CONSOLE_COLOR_WHITE
);
724 lcd_setbgcolor (CONSOLE_COLOR_BLACK
);
725 #endif /* CFG_WHITE_ON_BLACK */
727 #ifdef LCD_TEST_PATTERN
730 /* set framebuffer to background color */
731 memset ((char *)lcd_base
,
732 COLOR_MASK(lcd_getbgcolor()),
733 lcd_line_length
*panel_info
.vl_row
);
738 /* Paint the logo and retrieve LCD base address */
739 debug ("[LCD] Drawing the logo...\n");
740 lcd_console_address
= lcd_logo ();
742 /* Initialize the console */
744 #ifdef LCD_INFO_BELOW_LOGO
745 console_row
= 7 + BMP_LOGO_HEIGHT
/ VIDEO_FONT_HEIGHT
;
747 console_row
= 1; /* leave 1 blank line below logo */
755 /************************************************************************/
756 /* ** ROM capable initialization part - needed to reserve FB memory */
757 /************************************************************************/
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
764 * Note that this is running from ROM, so no write access to global data.
766 ulong
lcd_setmem (ulong addr
)
769 int line_length
= (panel_info
.vl_col
* NBITS (panel_info
.vl_bpix
)) / 8;
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
) );
774 size
= line_length
* panel_info
.vl_row
;
776 /* Round up to nearest full page */
777 size
= (size
+ (PAGE_SIZE
- 1)) & ~(PAGE_SIZE
- 1);
779 /* Allocate pages for the frame buffer. */
782 debug ("Reserving %ldk for LCD Framebuffer at: %08lx\n", size
>>10, addr
);
788 /************************************************************************/
789 /* ----------------- chipset specific functions ----------------------- */
790 /************************************************************************/
792 static void lcd_ctrl_init (void *lcdbase
)
794 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
795 volatile lcd823_t
*lcdp
= &immr
->im_lcd
;
800 /* Initialize the LCD control register according to the LCD
801 * parameters defined. We do everything here but enable
805 lccrtmp
= LCDBIT (LCCR_BNUM_BIT
,
806 (((panel_info
.vl_row
* panel_info
.vl_col
) * (1 << LCD_BPP
)) / 128));
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
);
820 lccrtmp
|= ((SIU_LEVEL5
/ 2) << 12);
821 lccrtmp
|= LCCR_EIEN
;
824 lcdp
->lcd_lccr
= lccrtmp
;
825 lcdp
->lcd_lcsr
= 0xFF; /* Clear pending interrupts */
827 /* Initialize LCD controller bus priorities.
830 immr
->im_siu_conf
.sc_sdcr
= (immr
->im_siu_conf
.sc_sdcr
& ~0x0f) | 1; /* RAID = 01, LAID = 00 */
832 immr
->im_siu_conf
.sc_sdcr
&= ~0x0f; /* RAID = LAID = 0 */
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).
842 immr
->im_clkrst
.car_sccr
&= ~0x1F;
843 immr
->im_clkrst
.car_sccr
|= LCD_DF
; /* was 8 */
845 #endif /* CONFIG_RBC823 */
847 #if defined(CONFIG_RBC823)
848 /* Enable LCD on port D.
850 immr
->im_ioport
.iop_pddat
&= 0x0300;
851 immr
->im_ioport
.iop_pdpar
|= 0x1CFF;
852 immr
->im_ioport
.iop_pddir
|= 0x1CFF;
854 /* Configure LCD_ON, VEE_ON, CCFL_ON on port B.
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.
862 immr
->im_ioport
.iop_pdpar
|= 0x1FFF;
863 immr
->im_ioport
.iop_pddir
|= 0x1FFF;
865 /* Enable LCD_A/B/C on port B.
867 immr
->im_cpm
.cp_pbpar
|= 0x00005001;
868 immr
->im_cpm
.cp_pbdir
|= 0x00005001;
870 /* Enable LCD on port D.
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;
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.
883 lcdp
->lcd_lcfaa
= (ulong
)lcd_base
;
884 lcdp
->lcd_lcfba
= (ulong
)lcd_base
;
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.
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 */
900 lcdp
->lcd_lchcr
= LCHCR_BO
|
901 LCDBIT (LCHCR_AT_BIT
, 4) |
902 LCDBIT (LCHCR_HPC_BIT
, lchcr_hpc_tmp
) |
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
) |
912 /*----------------------------------------------------------------------*/
914 #ifdef NOT_USED_SO_FAR
916 lcd_getcolreg (ushort regno
, ushort
*red
, ushort
*green
, ushort
*blue
)
918 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
919 volatile cpm8xx_t
*cp
= &(immr
->im_cpm
);
920 unsigned short colreg
, *cmap_ptr
;
922 cmap_ptr
= (unsigned short *)&cp
->lcd_cmap
[regno
* 2];
925 #ifdef CFG_INVERT_COLORS
929 *red
= (colreg
>> 8) & 0x0F;
930 *green
= (colreg
>> 4) & 0x0F;
931 *blue
= colreg
& 0x0F;
933 #endif /* NOT_USED_SO_FAR */
935 /*----------------------------------------------------------------------*/
937 #if LCD_BPP == LCD_COLOR8
939 lcd_setcolreg (ushort regno
, ushort red
, ushort green
, ushort blue
)
941 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
942 volatile cpm8xx_t
*cp
= &(immr
->im_cpm
);
943 unsigned short colreg
, *cmap_ptr
;
945 cmap_ptr
= (unsigned short *)&cp
->lcd_cmap
[regno
* 2];
947 colreg
= ((red
& 0x0F) << 8) |
948 ((green
& 0x0F) << 4) |
950 #ifdef CFG_INVERT_COLORS
955 debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %02X%02X\n",
956 regno
, &(cp
->lcd_cmap
[regno
* 2]),
958 cp
->lcd_cmap
[ regno
* 2 ], cp
->lcd_cmap
[(regno
* 2) + 1]);
960 #endif /* LCD_COLOR8 */
962 /*----------------------------------------------------------------------*/
964 #if LCD_BPP == LCD_MONOCHROME
966 void lcd_initcolregs (void)
968 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
969 volatile cpm8xx_t
*cp
= &(immr
->im_cpm
);
972 for (regno
= 0; regno
< 16; regno
++) {
973 cp
->lcd_cmap
[regno
* 2] = 0;
974 cp
->lcd_cmap
[(regno
* 2) + 1] = regno
& 0x0f;
979 /*----------------------------------------------------------------------*/
981 static void lcd_setfgcolor (int color
)
983 lcd_color_fg
= color
& 0x0F;
986 /*----------------------------------------------------------------------*/
988 static void lcd_setbgcolor (int color
)
990 lcd_color_bg
= color
& 0x0F;
993 /*----------------------------------------------------------------------*/
995 #ifdef NOT_USED_SO_FAR
996 static int lcd_getfgcolor (void)
1000 #endif /* NOT_USED_SO_FAR */
1002 /*----------------------------------------------------------------------*/
1004 static int lcd_getbgcolor (void)
1006 return lcd_color_bg
;
1009 /*----------------------------------------------------------------------*/
1011 static void lcd_enable (void)
1013 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
1014 volatile lcd823_t
*lcdp
= &immr
->im_lcd
;
1016 /* Enable the LCD panel */
1017 #ifndef CONFIG_RBC823
1018 immr
->im_siu_conf
.sc_sdcr
|= (1 << (31 - 25)); /* LAM = 1 */
1020 lcdp
->lcd_lccr
|= LCCR_PON
;
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;
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 */
1036 c
|= 0x07; /* Power on CCFL, Enable CCFL, Chip Enable LCD */
1038 pic_write (0x60, c
);
1040 #endif /* CONFIG_LWMON */
1042 #if defined(CONFIG_R360MPI)
1044 extern void r360_i2c_lcd_write (uchar data0
, uchar data1
);
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);
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;
1062 /*----------------------------------------------------------------------*/
1064 #if defined (CONFIG_RBC823)
1065 void lcd_disable (void)
1067 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
1068 volatile lcd823_t
*lcdp
= &immr
->im_lcd
;
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
);
1075 #elif defined(CONFIG_R360MPI)
1077 extern void r360_i2c_lcd_write (uchar data0
, uchar data1
);
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);
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;
1091 immr
->im_siu_conf
.sc_sdcr
&= ~(1 << (31 - 25)); /* LAM = 0 */
1092 #endif /* CONFIG_RBC823 */
1094 #endif /* NOT_USED_SO_FAR || CONFIG_RBC823 */
1097 /************************************************************************/
1098 /* ** Chipset depending Bitmap / Logo stuff... */
1099 /************************************************************************/
1102 #ifdef CONFIG_LCD_LOGO
1103 static void bitmap_plot (int x
, int y
)
1105 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
1106 volatile cpm8xx_t
*cp
= &(immr
->im_cpm
);
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
))
1117 /* Leave room for default color map */
1118 cmap
= (ushort
*)&(cp
->lcd_cmap
[BMP_LOGO_OFFSET
*sizeof(ushort
)]);
1123 for (i
=0; i
<(sizeof(bmp_logo_palette
)/(sizeof(ushort
))); ++i
) {
1124 ushort colreg
= bmp_logo_palette
[i
];
1125 #ifdef CFG_INVERT_COLORS
1131 bmap
= &bmp_logo_bitmap
[0];
1132 fb
= (char *)(lcd_base
+ y
* lcd_line_length
+ x
);
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
;
1144 #endif /* CONFIG_LCD_LOGO */
1146 #if (CONFIG_COMMANDS & CFG_CMD_BMP)
1148 * Display the BMP file located at address bmp_image.
1151 int lcd_display_bitmap(ulong bmp_image
)
1153 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
1154 volatile cpm8xx_t
*cp
= &(immr
->im_cpm
);
1158 bmp_image_t
*bmp
=(bmp_image_t
*)bmp_image
;
1161 unsigned long width
, height
;
1162 unsigned colors
,bpix
;
1163 unsigned long compression
;
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
);
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
);
1178 bpix
= NBITS(panel_info
.vl_bpix
);
1180 if ((bpix
!= 1) && (bpix
!= 8)) {
1181 printf ("Error: %d bit/pixel mode not supported by U-Boot\n",
1186 if (bpix
!= le16_to_cpu(bmp
->header
.bit_count
)) {
1187 printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
1189 le16_to_cpu(bmp
->header
.bit_count
));
1193 if (compression
!=BMP_BI_RGB
) {
1194 printf ("Error: compression type %ld not supported\n",
1199 debug ("Display-bmp: %d x %d with %d colors\n",
1200 width
, height
, colors
);
1203 /* Fill the entire color map */
1204 cmap
= (ushort
*)&(cp
->lcd_cmap
[255*sizeof(ushort
)]);
1207 for (i
= 0; i
< colors
; ++i
) {
1208 bmp_color_table_entry_t cte
= bmp
->color_table
[i
];
1210 ((cte
.red
>>4) << 8) |
1211 ((cte
.green
>>4) << 4) |
1213 #ifdef CFG_INVERT_COLORS
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
;
1228 bmap
= (uchar
*)bmp
+ le32_to_cpu (bmp
->header
.data_offset
);
1231 (((height
>=panel_info
.vl_row
) ? panel_info
.vl_row
: height
)-1)
1233 for (i
= 0; i
< height
; ++i
) {
1235 for (j
= 0; j
< width
; j
++)
1236 *(fb
++)=255-*(bmap
++);
1237 bmap
+= (width
- padded_line
);
1238 fb
-= (width
+ lcd_line_length
);
1243 #endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) */
1245 /*----------------------------------------------------------------------*/
1247 static void *lcd_logo (void)
1250 DECLARE_GLOBAL_DATA_PTR
;
1254 #endif /* LCD_INFO */
1256 #ifdef CONFIG_SPLASH_SCREEN
1260 if ((s
= getenv("splashimage")) != NULL
) {
1261 addr
= simple_strtoul(s
, NULL
, 16);
1263 if (lcd_display_bitmap (addr
) == 0) {
1264 return ((void *)lcd_base
);
1267 #endif /* CONFIG_SPLASH_SCREEN */
1269 #ifdef CONFIG_LCD_LOGO
1271 #endif /* CONFIG_LCD_LOGO */
1275 sprintf (info
, "%s (%s - %s) ", U_BOOT_VERSION
, __DATE__
, __TIME__
);
1276 lcd_drawchars (LCD_INFO_X
, LCD_INFO_Y
, info
, strlen(info
));
1278 sprintf (info
, "(C) 2003 DENX Software Engineering");
1279 lcd_drawchars (LCD_INFO_X
, LCD_INFO_Y
+ VIDEO_FONT_HEIGHT
,
1280 info
, strlen(info
));
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",
1292 gd
->bd
->bi_flashsize
>> 20 );
1293 lcd_drawchars (LCD_INFO_X
, LCD_INFO_Y
+ VIDEO_FONT_HEIGHT
* 4,
1294 info
, strlen(info
));
1296 /* leave one blank line */
1298 sprintf (info
, "MPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash",
1299 strmhz(temp
, gd
->cpu_clk
),
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 */
1307 #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
1308 return ((void *)((ulong
)lcd_base
+ BMP_LOGO_HEIGHT
* lcd_line_length
));
1310 return ((void *)lcd_base
);
1311 #endif /* CONFIG_LCD_LOGO */
1314 /************************************************************************/
1315 /************************************************************************/
1317 #endif /* CONFIG_LCD */