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