Blame view

common/lcd.c 28.9 KB
8655b6f86   wdenk   * Clean up tools/...
1
2
3
4
5
6
  /*
   * Common LCD routines for supported CPUs
   *
   * (C) Copyright 2001-2002
   * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
   *
3765b3e7b   Wolfgang Denk   Coding Style clea...
7
   * SPDX-License-Identifier:	GPL-2.0+
8655b6f86   wdenk   * Clean up tools/...
8
9
10
11
12
13
14
15
16
17
18
   */
  
  /************************************************************************/
  /* ** HEADER FILES							*/
  /************************************************************************/
  
  /* #define DEBUG */
  
  #include <config.h>
  #include <common.h>
  #include <command.h>
8655b6f86   wdenk   * Clean up tools/...
19
  #include <stdarg.h>
c08804853   Nikita Kiryanov   lcd: implement a ...
20
21
  #include <search.h>
  #include <env_callback.h>
8655b6f86   wdenk   * Clean up tools/...
22
  #include <linux/types.h>
52cb4d4fb   Jean-Christophe PLAGNIOL-VILLARD   stdio/device: rew...
23
  #include <stdio_dev.h>
8655b6f86   wdenk   * Clean up tools/...
24
25
26
27
  #if defined(CONFIG_POST)
  #include <post.h>
  #endif
  #include <lcd.h>
8b0bfc680   wdenk   * Patch by Yuli B...
28
  #include <watchdog.h>
dca2a1c18   Przemyslaw Marczak   common: lcd.c: fi...
29
  #include <asm/unaligned.h>
dd4425e85   Robert Winkler   video: lcd: Add C...
30
  #include <splash.h>
abc20aba1   Marek Vasut   PXA: Rename CONFI...
31
32
33
  #if defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \
  	defined(CONFIG_CPU_MONAHANS)
  #define CONFIG_CPU_PXA
8655b6f86   wdenk   * Clean up tools/...
34
35
36
37
  #include <asm/byteorder.h>
  #endif
  
  #if defined(CONFIG_MPC823)
8655b6f86   wdenk   * Clean up tools/...
38
39
  #include <lcdvideo.h>
  #endif
39cf48048   Stelian Pop   Add ATMEL LCD driver
40
41
  #if defined(CONFIG_ATMEL_LCD)
  #include <atmel_lcdc.h>
39cf48048   Stelian Pop   Add ATMEL LCD driver
42
  #endif
6a195d2d8   Stephen Warren   lcd: add function...
43
44
45
  #if defined(CONFIG_LCD_DT_SIMPLEFB)
  #include <libfdt.h>
  #endif
8655b6f86   wdenk   * Clean up tools/...
46
47
48
49
  /************************************************************************/
  /* ** FONT DATA								*/
  /************************************************************************/
  #include <video_font.h>		/* Get font data, width and height	*/
88804d19e   wdenk   * Patch by Detlev...
50
51
52
53
54
  /************************************************************************/
  /* ** LOGO DATA								*/
  /************************************************************************/
  #ifdef CONFIG_LCD_LOGO
  # include <bmp_logo.h>		/* Get logo data, width and height	*/
c270730f5   Che-Liang Chiou   tools: logo: spli...
55
  # include <bmp_logo_data.h>
acb138689   Alessandro Rubini   lcd: make 16bpp work
56
  # if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET) && (LCD_BPP != LCD_COLOR16)
88804d19e   wdenk   * Patch by Detlev...
57
58
59
  #  error Default Color Map overlaps with Logo Color Map
  # endif
  #endif
8655b6f86   wdenk   * Clean up tools/...
60

676d319ef   Simon Glass   lcd: Add CONFIG_L...
61
62
63
  #ifndef CONFIG_LCD_ALIGNMENT
  #define CONFIG_LCD_ALIGNMENT PAGE_SIZE
  #endif
0d89efef7   Simon Glass   lcd: Add CONFIG_C...
64
65
66
67
  /* By default we scroll by a single line */
  #ifndef CONFIG_CONSOLE_SCROLL_LINES
  #define CONFIG_CONSOLE_SCROLL_LINES 1
  #endif
a5796c51c   Jeroen Hofstee   common/lcd.c: mov...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  /************************************************************************/
  /* ** CONSOLE DEFINITIONS & FUNCTIONS					*/
  /************************************************************************/
  #if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
  # define CONSOLE_ROWS		((panel_info.vl_row-BMP_LOGO_HEIGHT) \
  					/ VIDEO_FONT_HEIGHT)
  #else
  # define CONSOLE_ROWS		(panel_info.vl_row / VIDEO_FONT_HEIGHT)
  #endif
  
  #define CONSOLE_COLS		(panel_info.vl_col / VIDEO_FONT_WIDTH)
  #define CONSOLE_ROW_SIZE	(VIDEO_FONT_HEIGHT * lcd_line_length)
  #define CONSOLE_ROW_FIRST	lcd_console_address
  #define CONSOLE_ROW_SECOND	(lcd_console_address + CONSOLE_ROW_SIZE)
  #define CONSOLE_ROW_LAST	(lcd_console_address + CONSOLE_SIZE \
  					- CONSOLE_ROW_SIZE)
  #define CONSOLE_SIZE		(CONSOLE_ROW_SIZE * CONSOLE_ROWS)
  #define CONSOLE_SCROLL_SIZE	(CONSOLE_SIZE - CONSOLE_ROW_SIZE)
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
86

a5796c51c   Jeroen Hofstee   common/lcd.c: mov...
87
88
89
90
91
92
93
94
  #if LCD_BPP == LCD_MONOCHROME
  # define COLOR_MASK(c)		((c)	  | (c) << 1 | (c) << 2 | (c) << 3 | \
  				 (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7)
  #elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16)
  # define COLOR_MASK(c)		(c)
  #else
  # error Unsupported LCD BPP.
  #endif
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
95
  DECLARE_GLOBAL_DATA_PTR;
8655b6f86   wdenk   * Clean up tools/...
96

8f47d917c   Nikita Kiryanov   common lcd: minor...
97
98
99
  static void lcd_drawchars(ushort x, ushort y, uchar *str, int count);
  static inline void lcd_puts_xy(ushort x, ushort y, uchar *s);
  static inline void lcd_putc_xy(ushort x, ushort y, uchar  c);
8655b6f86   wdenk   * Clean up tools/...
100

8f47d917c   Nikita Kiryanov   common lcd: minor...
101
  static int lcd_init(void *lcdbase);
8655b6f86   wdenk   * Clean up tools/...
102

6b035141f   Jeroen Hofstee   common/lcd: cosme...
103
  static void *lcd_logo(void);
8655b6f86   wdenk   * Clean up tools/...
104

8f47d917c   Nikita Kiryanov   common lcd: minor...
105
106
107
  static int lcd_getbgcolor(void);
  static void lcd_setfgcolor(int color);
  static void lcd_setbgcolor(int color);
8655b6f86   wdenk   * Clean up tools/...
108

46d1d5dd4   Wolfgang Denk   common/lcd.c: cle...
109
110
  static int lcd_color_fg;
  static int lcd_color_bg;
f1d205a19   Jeroen Hofstee   common/lcd.c: cle...
111
  int lcd_line_length;
46d1d5dd4   Wolfgang Denk   common/lcd.c: cle...
112

8655b6f86   wdenk   * Clean up tools/...
113
  char lcd_is_enabled = 0;
8655b6f86   wdenk   * Clean up tools/...
114

f1d205a19   Jeroen Hofstee   common/lcd.c: cle...
115
116
  static short console_col;
  static short console_row;
9a8efc460   Simon Glass   lcd: Add support ...
117

f1d205a19   Jeroen Hofstee   common/lcd.c: cle...
118
  static void *lcd_console_address;
00a0ca598   Jeroen Hofstee   common/lcd.c: rem...
119
  static void *lcd_base;			/* Start of framebuffer memory	*/
9a8efc460   Simon Glass   lcd: Add support ...
120

9a8efc460   Simon Glass   lcd: Add support ...
121
  static char lcd_flush_dcache;	/* 1 to flush dcache after each lcd update */
8655b6f86   wdenk   * Clean up tools/...
122
123
  
  /************************************************************************/
9a8efc460   Simon Glass   lcd: Add support ...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  /* Flush LCD activity to the caches */
  void lcd_sync(void)
  {
  	/*
  	 * flush_dcache_range() is declared in common.h but it seems that some
  	 * architectures do not actually implement it. Is there a way to find
  	 * out whether it exists? For now, ARM is safe.
  	 */
  #if defined(CONFIG_ARM) && !defined(CONFIG_SYS_DCACHE_OFF)
  	int line_length;
  
  	if (lcd_flush_dcache)
  		flush_dcache_range((u32)lcd_base,
  			(u32)(lcd_base + lcd_get_size(&line_length)));
  #endif
  }
  
  void lcd_set_flush_dcache(int flush)
  {
  	lcd_flush_dcache = (flush != 0);
  }
8655b6f86   wdenk   * Clean up tools/...
145
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
146
  static void console_scrollup(void)
8655b6f86   wdenk   * Clean up tools/...
147
  {
0d89efef7   Simon Glass   lcd: Add CONFIG_C...
148
149
150
151
152
153
154
155
156
157
  	const int rows = CONFIG_CONSOLE_SCROLL_LINES;
  
  	/* Copy up rows ignoring those that will be overwritten */
  	memcpy(CONSOLE_ROW_FIRST,
  	       lcd_console_address + CONSOLE_ROW_SIZE * rows,
  	       CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
  
  	/* Clear the last rows */
  	memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
  		COLOR_MASK(lcd_color_bg),
6b035141f   Jeroen Hofstee   common/lcd: cosme...
158
  		CONSOLE_ROW_SIZE * rows);
8655b6f86   wdenk   * Clean up tools/...
159

9a8efc460   Simon Glass   lcd: Add support ...
160
  	lcd_sync();
0d89efef7   Simon Glass   lcd: Add CONFIG_C...
161
  	console_row -= rows;
8655b6f86   wdenk   * Clean up tools/...
162
163
164
  }
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
165
  static inline void console_back(void)
8655b6f86   wdenk   * Clean up tools/...
166
167
168
  {
  	if (--console_col < 0) {
  		console_col = CONSOLE_COLS-1 ;
6b035141f   Jeroen Hofstee   common/lcd: cosme...
169
  		if (--console_row < 0)
8655b6f86   wdenk   * Clean up tools/...
170
  			console_row = 0;
8655b6f86   wdenk   * Clean up tools/...
171
  	}
8f47d917c   Nikita Kiryanov   common lcd: minor...
172
173
  	lcd_putc_xy(console_col * VIDEO_FONT_WIDTH,
  		console_row * VIDEO_FONT_HEIGHT, ' ');
8655b6f86   wdenk   * Clean up tools/...
174
175
176
  }
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
177
  static inline void console_newline(void)
8655b6f86   wdenk   * Clean up tools/...
178
  {
8655b6f86   wdenk   * Clean up tools/...
179
180
181
  	console_col = 0;
  
  	/* Check if we need to scroll the terminal */
6b035141f   Jeroen Hofstee   common/lcd: cosme...
182
  	if (++console_row >= CONSOLE_ROWS)
8f47d917c   Nikita Kiryanov   common lcd: minor...
183
  		console_scrollup();
6b035141f   Jeroen Hofstee   common/lcd: cosme...
184
  	else
9a8efc460   Simon Glass   lcd: Add support ...
185
  		lcd_sync();
8655b6f86   wdenk   * Clean up tools/...
186
187
188
  }
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
189
  void lcd_putc(const char c)
8655b6f86   wdenk   * Clean up tools/...
190
191
192
  {
  	if (!lcd_is_enabled) {
  		serial_putc(c);
8f47d917c   Nikita Kiryanov   common lcd: minor...
193

8655b6f86   wdenk   * Clean up tools/...
194
195
196
197
  		return;
  	}
  
  	switch (c) {
8f47d917c   Nikita Kiryanov   common lcd: minor...
198
199
  	case '\r':
  		console_col = 0;
8655b6f86   wdenk   * Clean up tools/...
200

8f47d917c   Nikita Kiryanov   common lcd: minor...
201
202
203
204
  		return;
  	case '
  ':
  		console_newline();
8655b6f86   wdenk   * Clean up tools/...
205

8f47d917c   Nikita Kiryanov   common lcd: minor...
206
  		return;
8655b6f86   wdenk   * Clean up tools/...
207
  	case '\t':	/* Tab (8 chars alignment) */
8f47d917c   Nikita Kiryanov   common lcd: minor...
208
209
  		console_col +=  8;
  		console_col &= ~7;
8655b6f86   wdenk   * Clean up tools/...
210

8f47d917c   Nikita Kiryanov   common lcd: minor...
211
212
  		if (console_col >= CONSOLE_COLS)
  			console_newline();
8655b6f86   wdenk   * Clean up tools/...
213

8f47d917c   Nikita Kiryanov   common lcd: minor...
214
215
216
  		return;
  	case '\b':
  		console_back();
8655b6f86   wdenk   * Clean up tools/...
217

8f47d917c   Nikita Kiryanov   common lcd: minor...
218
219
220
221
222
223
  		return;
  	default:
  		lcd_putc_xy(console_col * VIDEO_FONT_WIDTH,
  			console_row * VIDEO_FONT_HEIGHT, c);
  		if (++console_col >= CONSOLE_COLS)
  			console_newline();
8655b6f86   wdenk   * Clean up tools/...
224
  	}
8655b6f86   wdenk   * Clean up tools/...
225
226
227
  }
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
228
  void lcd_puts(const char *s)
8655b6f86   wdenk   * Clean up tools/...
229
230
  {
  	if (!lcd_is_enabled) {
8f47d917c   Nikita Kiryanov   common lcd: minor...
231
  		serial_puts(s);
8655b6f86   wdenk   * Clean up tools/...
232
233
  		return;
  	}
6b035141f   Jeroen Hofstee   common/lcd: cosme...
234
  	while (*s)
8f47d917c   Nikita Kiryanov   common lcd: minor...
235
  		lcd_putc(*s++);
6b035141f   Jeroen Hofstee   common/lcd: cosme...
236

9a8efc460   Simon Glass   lcd: Add support ...
237
  	lcd_sync();
8655b6f86   wdenk   * Clean up tools/...
238
  }
15b17ab52   Haavard Skinnemoen   lcd: Implement lc...
239
240
241
242
243
244
245
246
247
248
249
250
251
  /*----------------------------------------------------------------------*/
  
  void lcd_printf(const char *fmt, ...)
  {
  	va_list args;
  	char buf[CONFIG_SYS_PBSIZE];
  
  	va_start(args, fmt);
  	vsprintf(buf, fmt, args);
  	va_end(args);
  
  	lcd_puts(buf);
  }
8655b6f86   wdenk   * Clean up tools/...
252
253
254
  /************************************************************************/
  /* ** Low-Level Graphics Routines					*/
  /************************************************************************/
8f47d917c   Nikita Kiryanov   common lcd: minor...
255
  static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)
8655b6f86   wdenk   * Clean up tools/...
256
257
  {
  	uchar *dest;
be547c6db   Marek Vasut   GCC4.6: Squash wa...
258
  	ushort row;
0f999c49e   Anatolij Gustschin   common/lcd.c: red...
259
260
261
  #if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
  	y += BMP_LOGO_HEIGHT;
  #endif
be547c6db   Marek Vasut   GCC4.6: Squash wa...
262
263
264
  #if LCD_BPP == LCD_MONOCHROME
  	ushort off  = x * (1 << LCD_BPP) % 8;
  #endif
8655b6f86   wdenk   * Clean up tools/...
265
266
  
  	dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8);
8655b6f86   wdenk   * Clean up tools/...
267

8f47d917c   Nikita Kiryanov   common lcd: minor...
268
  	for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
8655b6f86   wdenk   * Clean up tools/...
269
  		uchar *s = str;
8655b6f86   wdenk   * Clean up tools/...
270
  		int i;
acb138689   Alessandro Rubini   lcd: make 16bpp work
271
272
273
274
275
  #if LCD_BPP == LCD_COLOR16
  		ushort *d = (ushort *)dest;
  #else
  		uchar *d = dest;
  #endif
8655b6f86   wdenk   * Clean up tools/...
276
277
  
  #if LCD_BPP == LCD_MONOCHROME
6b035141f   Jeroen Hofstee   common/lcd: cosme...
278
  		uchar rest = *d & -(1 << (8 - off));
8655b6f86   wdenk   * Clean up tools/...
279
280
  		uchar sym;
  #endif
8f47d917c   Nikita Kiryanov   common lcd: minor...
281
  		for (i = 0; i < count; ++i) {
8655b6f86   wdenk   * Clean up tools/...
282
283
284
285
286
287
288
  			uchar c, bits;
  
  			c = *s++;
  			bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
  
  #if LCD_BPP == LCD_MONOCHROME
  			sym  = (COLOR_MASK(lcd_color_fg) & bits) |
8f47d917c   Nikita Kiryanov   common lcd: minor...
289
  				(COLOR_MASK(lcd_color_bg) & ~bits);
8655b6f86   wdenk   * Clean up tools/...
290
291
292
293
  
  			*d++ = rest | (sym >> off);
  			rest = sym << (8-off);
  #elif LCD_BPP == LCD_COLOR8
8f47d917c   Nikita Kiryanov   common lcd: minor...
294
  			for (c = 0; c < 8; ++c) {
8655b6f86   wdenk   * Clean up tools/...
295
296
297
298
299
  				*d++ = (bits & 0x80) ?
  						lcd_color_fg : lcd_color_bg;
  				bits <<= 1;
  			}
  #elif LCD_BPP == LCD_COLOR16
8f47d917c   Nikita Kiryanov   common lcd: minor...
300
  			for (c = 0; c < 8; ++c) {
8655b6f86   wdenk   * Clean up tools/...
301
302
303
304
305
306
307
  				*d++ = (bits & 0x80) ?
  						lcd_color_fg : lcd_color_bg;
  				bits <<= 1;
  			}
  #endif
  		}
  #if LCD_BPP == LCD_MONOCHROME
6b035141f   Jeroen Hofstee   common/lcd: cosme...
308
  		*d  = rest | (*d & ((1 << (8 - off)) - 1));
8655b6f86   wdenk   * Clean up tools/...
309
310
311
312
313
  #endif
  	}
  }
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
314
  static inline void lcd_puts_xy(ushort x, ushort y, uchar *s)
8655b6f86   wdenk   * Clean up tools/...
315
  {
0f999c49e   Anatolij Gustschin   common/lcd.c: red...
316
  	lcd_drawchars(x, y, s, strlen((char *)s));
8655b6f86   wdenk   * Clean up tools/...
317
318
319
  }
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
320
  static inline void lcd_putc_xy(ushort x, ushort y, uchar c)
8655b6f86   wdenk   * Clean up tools/...
321
  {
0f999c49e   Anatolij Gustschin   common/lcd.c: red...
322
  	lcd_drawchars(x, y, &c, 1);
8655b6f86   wdenk   * Clean up tools/...
323
324
325
326
327
328
329
330
331
  }
  
  /************************************************************************/
  /**  Small utility to check that you got the colours right		*/
  /************************************************************************/
  #ifdef LCD_TEST_PATTERN
  
  #define	N_BLK_VERT	2
  #define	N_BLK_HOR	3
6b035141f   Jeroen Hofstee   common/lcd: cosme...
332
  static int test_colors[N_BLK_HOR * N_BLK_VERT] = {
8655b6f86   wdenk   * Clean up tools/...
333
334
335
  	CONSOLE_COLOR_RED,	CONSOLE_COLOR_GREEN,	CONSOLE_COLOR_YELLOW,
  	CONSOLE_COLOR_BLUE,	CONSOLE_COLOR_MAGENTA,	CONSOLE_COLOR_CYAN,
  };
8f47d917c   Nikita Kiryanov   common lcd: minor...
336
  static void test_pattern(void)
8655b6f86   wdenk   * Clean up tools/...
337
338
339
340
341
342
343
  {
  	ushort v_max  = panel_info.vl_row;
  	ushort h_max  = panel_info.vl_col;
  	ushort v_step = (v_max + N_BLK_VERT - 1) / N_BLK_VERT;
  	ushort h_step = (h_max + N_BLK_HOR  - 1) / N_BLK_HOR;
  	ushort v, h;
  	uchar *pix = (uchar *)lcd_base;
8f47d917c   Nikita Kiryanov   common lcd: minor...
344
345
  	printf("[LCD] Test Pattern: %d x %d [%d x %d]
  ",
8655b6f86   wdenk   * Clean up tools/...
346
347
348
  		h_max, v_max, h_step, v_step);
  
  	/* WARNING: Code silently assumes 8bit/pixel */
8f47d917c   Nikita Kiryanov   common lcd: minor...
349
  	for (v = 0; v < v_max; ++v) {
8655b6f86   wdenk   * Clean up tools/...
350
  		uchar iy = v / v_step;
8f47d917c   Nikita Kiryanov   common lcd: minor...
351
  		for (h = 0; h < h_max; ++h) {
6b035141f   Jeroen Hofstee   common/lcd: cosme...
352
  			uchar ix = N_BLK_HOR * iy + h / h_step;
8655b6f86   wdenk   * Clean up tools/...
353
354
355
356
357
358
359
360
361
362
  			*pix++ = test_colors[ix];
  		}
  	}
  }
  #endif /* LCD_TEST_PATTERN */
  
  
  /************************************************************************/
  /* ** GENERIC Initialization Routines					*/
  /************************************************************************/
cefa47171   Anatolij Gustschin   lcd: allow overri...
363
364
365
366
367
368
369
  /*
   * With most lcd drivers the line length is set up
   * by calculating it from panel_info parameters. Some
   * drivers need to calculate the line length differently,
   * so make the function weak to allow overriding it.
   */
  __weak int lcd_get_size(int *line_length)
676d319ef   Simon Glass   lcd: Add CONFIG_L...
370
371
372
373
  {
  	*line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
  	return *line_length * panel_info.vl_row;
  }
6b035141f   Jeroen Hofstee   common/lcd: cosme...
374
  int drv_lcd_init(void)
8655b6f86   wdenk   * Clean up tools/...
375
  {
52cb4d4fb   Jean-Christophe PLAGNIOL-VILLARD   stdio/device: rew...
376
  	struct stdio_dev lcddev;
8655b6f86   wdenk   * Clean up tools/...
377
  	int rc;
6b035141f   Jeroen Hofstee   common/lcd: cosme...
378
  	lcd_base = (void *) gd->fb_base;
8655b6f86   wdenk   * Clean up tools/...
379

8f47d917c   Nikita Kiryanov   common lcd: minor...
380
  	lcd_init(lcd_base);		/* LCD initialization */
8655b6f86   wdenk   * Clean up tools/...
381
382
  
  	/* Device initialization */
8f47d917c   Nikita Kiryanov   common lcd: minor...
383
  	memset(&lcddev, 0, sizeof(lcddev));
8655b6f86   wdenk   * Clean up tools/...
384

8f47d917c   Nikita Kiryanov   common lcd: minor...
385
  	strcpy(lcddev.name, "lcd");
8655b6f86   wdenk   * Clean up tools/...
386
387
388
389
  	lcddev.ext   = 0;			/* No extensions */
  	lcddev.flags = DEV_FLAGS_OUTPUT;	/* Output only */
  	lcddev.putc  = lcd_putc;		/* 'putc' function */
  	lcddev.puts  = lcd_puts;		/* 'puts' function */
6b035141f   Jeroen Hofstee   common/lcd: cosme...
390
  	rc = stdio_register(&lcddev);
8655b6f86   wdenk   * Clean up tools/...
391
392
393
394
395
  
  	return (rc == 0) ? 1 : rc;
  }
  
  /*----------------------------------------------------------------------*/
02110903a   Che-Liang Chiou   lcd: add clear an...
396
  void lcd_clear(void)
8655b6f86   wdenk   * Clean up tools/...
397
398
399
400
401
402
403
  {
  #if LCD_BPP == LCD_MONOCHROME
  	/* Setting the palette */
  	lcd_initcolregs();
  
  #elif LCD_BPP == LCD_COLOR8
  	/* Setting the palette */
8f47d917c   Nikita Kiryanov   common lcd: minor...
404
405
406
407
408
409
410
411
412
  	lcd_setcolreg(CONSOLE_COLOR_BLACK, 0, 0, 0);
  	lcd_setcolreg(CONSOLE_COLOR_RED, 0xFF, 0, 0);
  	lcd_setcolreg(CONSOLE_COLOR_GREEN, 0, 0xFF, 0);
  	lcd_setcolreg(CONSOLE_COLOR_YELLOW, 0xFF, 0xFF, 0);
  	lcd_setcolreg(CONSOLE_COLOR_BLUE, 0, 0, 0xFF);
  	lcd_setcolreg(CONSOLE_COLOR_MAGENTA, 0xFF, 0, 0xFF);
  	lcd_setcolreg(CONSOLE_COLOR_CYAN, 0, 0xFF, 0xFF);
  	lcd_setcolreg(CONSOLE_COLOR_GREY, 0xAA, 0xAA, 0xAA);
  	lcd_setcolreg(CONSOLE_COLOR_WHITE, 0xFF, 0xFF, 0xFF);
8655b6f86   wdenk   * Clean up tools/...
413
  #endif
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
414
  #ifndef CONFIG_SYS_WHITE_ON_BLACK
8f47d917c   Nikita Kiryanov   common lcd: minor...
415
416
  	lcd_setfgcolor(CONSOLE_COLOR_BLACK);
  	lcd_setbgcolor(CONSOLE_COLOR_WHITE);
8655b6f86   wdenk   * Clean up tools/...
417
  #else
8f47d917c   Nikita Kiryanov   common lcd: minor...
418
419
  	lcd_setfgcolor(CONSOLE_COLOR_WHITE);
  	lcd_setbgcolor(CONSOLE_COLOR_BLACK);
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
420
  #endif	/* CONFIG_SYS_WHITE_ON_BLACK */
8655b6f86   wdenk   * Clean up tools/...
421
422
423
424
425
  
  #ifdef	LCD_TEST_PATTERN
  	test_pattern();
  #else
  	/* set framebuffer to background color */
8f47d917c   Nikita Kiryanov   common lcd: minor...
426
  	memset((char *)lcd_base,
8655b6f86   wdenk   * Clean up tools/...
427
  		COLOR_MASK(lcd_getbgcolor()),
6b035141f   Jeroen Hofstee   common/lcd: cosme...
428
  		lcd_line_length * panel_info.vl_row);
8655b6f86   wdenk   * Clean up tools/...
429
430
  #endif
  	/* Paint the logo and retrieve LCD base address */
8f47d917c   Nikita Kiryanov   common lcd: minor...
431
432
  	debug("[LCD] Drawing the logo...
  ");
6b035141f   Jeroen Hofstee   common/lcd: cosme...
433
  	lcd_console_address = lcd_logo();
8655b6f86   wdenk   * Clean up tools/...
434
435
436
  
  	console_col = 0;
  	console_row = 0;
9a8efc460   Simon Glass   lcd: Add support ...
437
438
439
440
441
442
443
444
  	lcd_sync();
  }
  
  static int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc,
  			char *const argv[])
  {
  	lcd_clear();
  	return 0;
8655b6f86   wdenk   * Clean up tools/...
445
446
447
  }
  
  U_BOOT_CMD(
02110903a   Che-Liang Chiou   lcd: add clear an...
448
  	cls,	1,	1,	do_lcd_clear,
2fb2604d5   Peter Tyser   Command usage cle...
449
  	"clear screen",
a89c33db9   Wolfgang Denk   General help mess...
450
  	""
8655b6f86   wdenk   * Clean up tools/...
451
452
453
  );
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
454
  static int lcd_init(void *lcdbase)
8655b6f86   wdenk   * Clean up tools/...
455
456
  {
  	/* Initialize the lcd controller */
8f47d917c   Nikita Kiryanov   common lcd: minor...
457
458
  	debug("[LCD] Initializing LCD frambuffer at %p
  ", lcdbase);
8655b6f86   wdenk   * Clean up tools/...
459

8f47d917c   Nikita Kiryanov   common lcd: minor...
460
  	lcd_ctrl_init(lcdbase);
1d3dea12e   Anatolij Gustschin   video: bcm2835: f...
461
462
463
464
465
466
467
468
469
470
471
472
  
  	/*
  	 * lcd_ctrl_init() of some drivers (i.e. bcm2835 on rpi_b) ignores
  	 * the 'lcdbase' argument and uses custom lcd base address
  	 * by setting up gd->fb_base. Check for this condition and fixup
  	 * 'lcd_base' address.
  	 */
  	if ((unsigned long)lcdbase != gd->fb_base)
  		lcd_base = (void *)gd->fb_base;
  
  	debug("[LCD] Using LCD frambuffer at %p
  ", lcd_base);
6d3307195   Stephen Warren   lcd: calculate li...
473
  	lcd_get_size(&lcd_line_length);
6f93d2b8f   Haavard Skinnemoen   lcd: Set lcd_is_e...
474
  	lcd_is_enabled = 1;
02110903a   Che-Liang Chiou   lcd: add clear an...
475
  	lcd_clear();
6b035141f   Jeroen Hofstee   common/lcd: cosme...
476
  	lcd_enable();
8655b6f86   wdenk   * Clean up tools/...
477
478
479
  
  	/* Initialize the console */
  	console_col = 0;
88804d19e   wdenk   * Patch by Detlev...
480
  #ifdef CONFIG_LCD_INFO_BELOW_LOGO
8655b6f86   wdenk   * Clean up tools/...
481
482
483
484
  	console_row = 7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT;
  #else
  	console_row = 1;	/* leave 1 blank line below logo */
  #endif
8655b6f86   wdenk   * Clean up tools/...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  
  	return 0;
  }
  
  
  /************************************************************************/
  /* ** ROM capable initialization part - needed to reserve FB memory	*/
  /************************************************************************/
  /*
   * This is called early in the system initialization to grab memory
   * for the LCD controller.
   * Returns new address for monitor, after reserving LCD buffer memory
   *
   * Note that this is running from ROM, so no write access to global data.
   */
8f47d917c   Nikita Kiryanov   common lcd: minor...
500
  ulong lcd_setmem(ulong addr)
8655b6f86   wdenk   * Clean up tools/...
501
502
  {
  	ulong size;
676d319ef   Simon Glass   lcd: Add CONFIG_L...
503
  	int line_length;
8655b6f86   wdenk   * Clean up tools/...
504

8f47d917c   Nikita Kiryanov   common lcd: minor...
505
506
507
  	debug("LCD panel info: %d x %d, %d bit/pix
  ", panel_info.vl_col,
  		panel_info.vl_row, NBITS(panel_info.vl_bpix));
8655b6f86   wdenk   * Clean up tools/...
508

676d319ef   Simon Glass   lcd: Add CONFIG_L...
509
  	size = lcd_get_size(&line_length);
8655b6f86   wdenk   * Clean up tools/...
510

676d319ef   Simon Glass   lcd: Add CONFIG_L...
511
512
513
  	/* Round up to nearest full page, or MMU section if defined */
  	size = ALIGN(size, CONFIG_LCD_ALIGNMENT);
  	addr = ALIGN(addr - CONFIG_LCD_ALIGNMENT + 1, CONFIG_LCD_ALIGNMENT);
8655b6f86   wdenk   * Clean up tools/...
514
515
516
  
  	/* Allocate pages for the frame buffer. */
  	addr -= size;
6b035141f   Jeroen Hofstee   common/lcd: cosme...
517
518
519
  	debug("Reserving %ldk for LCD Framebuffer at: %08lx
  ",
  	      size >> 10, addr);
8655b6f86   wdenk   * Clean up tools/...
520

8f47d917c   Nikita Kiryanov   common lcd: minor...
521
  	return addr;
8655b6f86   wdenk   * Clean up tools/...
522
523
524
  }
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
525
  static void lcd_setfgcolor(int color)
8655b6f86   wdenk   * Clean up tools/...
526
  {
39cf48048   Stelian Pop   Add ATMEL LCD driver
527
  	lcd_color_fg = color;
8655b6f86   wdenk   * Clean up tools/...
528
529
530
  }
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
531
  static void lcd_setbgcolor(int color)
8655b6f86   wdenk   * Clean up tools/...
532
  {
39cf48048   Stelian Pop   Add ATMEL LCD driver
533
  	lcd_color_bg = color;
8655b6f86   wdenk   * Clean up tools/...
534
535
536
  }
  
  /*----------------------------------------------------------------------*/
46d1d5dd4   Wolfgang Denk   common/lcd.c: cle...
537
  int lcd_getfgcolor(void)
8655b6f86   wdenk   * Clean up tools/...
538
539
540
  {
  	return lcd_color_fg;
  }
8655b6f86   wdenk   * Clean up tools/...
541
542
  
  /*----------------------------------------------------------------------*/
8f47d917c   Nikita Kiryanov   common lcd: minor...
543
  static int lcd_getbgcolor(void)
8655b6f86   wdenk   * Clean up tools/...
544
545
546
  {
  	return lcd_color_bg;
  }
8655b6f86   wdenk   * Clean up tools/...
547
548
549
  /************************************************************************/
  /* ** Chipset depending Bitmap / Logo stuff...                          */
  /************************************************************************/
203c37b8c   Nikita Kiryanov   common lcd: simpl...
550
551
552
553
554
555
556
557
558
559
560
  static inline ushort *configuration_get_cmap(void)
  {
  #if defined CONFIG_CPU_PXA
  	struct pxafb_info *fbi = &panel_info.pxa;
  	return (ushort *)fbi->palette;
  #elif defined(CONFIG_MPC823)
  	immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  	cpm8xx_t *cp = &(immr->im_cpm);
  	return (ushort *)&(cp->lcd_cmap[255 * sizeof(ushort)]);
  #elif defined(CONFIG_ATMEL_LCD)
  	return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0));
d23019f3d   Anatolij Gustschin   common/lcd: fix b...
561
562
  #elif !defined(CONFIG_ATMEL_HLCD) && !defined(CONFIG_EXYNOS_FB)
  	return panel_info.cmap;
6b035141f   Jeroen Hofstee   common/lcd: cosme...
563
  #elif defined(CONFIG_LCD_LOGO)
d23019f3d   Anatolij Gustschin   common/lcd: fix b...
564
565
566
567
  	return bmp_logo_palette;
  #else
  	return NULL;
  #endif
203c37b8c   Nikita Kiryanov   common lcd: simpl...
568
  }
8655b6f86   wdenk   * Clean up tools/...
569
  #ifdef CONFIG_LCD_LOGO
8f47d917c   Nikita Kiryanov   common lcd: minor...
570
  void bitmap_plot(int x, int y)
8655b6f86   wdenk   * Clean up tools/...
571
  {
39cf48048   Stelian Pop   Add ATMEL LCD driver
572
  #ifdef CONFIG_ATMEL_LCD
203c37b8c   Nikita Kiryanov   common lcd: simpl...
573
  	uint *cmap = (uint *)bmp_logo_palette;
39cf48048   Stelian Pop   Add ATMEL LCD driver
574
  #else
203c37b8c   Nikita Kiryanov   common lcd: simpl...
575
  	ushort *cmap = (ushort *)bmp_logo_palette;
39cf48048   Stelian Pop   Add ATMEL LCD driver
576
  #endif
8655b6f86   wdenk   * Clean up tools/...
577
578
579
580
  	ushort i, j;
  	uchar *bmap;
  	uchar *fb;
  	ushort *fb16;
203c37b8c   Nikita Kiryanov   common lcd: simpl...
581
582
583
  #if defined(CONFIG_MPC823)
  	immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  	cpm8xx_t *cp = &(immr->im_cpm);
8655b6f86   wdenk   * Clean up tools/...
584
  #endif
317461c1d   Andre Renaud   Fix bitmap offset...
585
  	unsigned bpix = NBITS(panel_info.vl_bpix);
8655b6f86   wdenk   * Clean up tools/...
586

8f47d917c   Nikita Kiryanov   common lcd: minor...
587
588
  	debug("Logo: width %d  height %d  colors %d  cmap %d
  ",
8655b6f86   wdenk   * Clean up tools/...
589
  		BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS,
095407da5   Anatolij Gustschin   common/lcd.c: use...
590
  		ARRAY_SIZE(bmp_logo_palette));
8655b6f86   wdenk   * Clean up tools/...
591
592
  
  	bmap = &bmp_logo_bitmap[0];
317461c1d   Andre Renaud   Fix bitmap offset...
593
  	fb   = (uchar *)(lcd_base + y * lcd_line_length + x * bpix / 8);
8655b6f86   wdenk   * Clean up tools/...
594

317461c1d   Andre Renaud   Fix bitmap offset...
595
  	if (bpix < 12) {
203c37b8c   Nikita Kiryanov   common lcd: simpl...
596
597
598
599
600
601
  		/* Leave room for default color map
  		 * default case: generic system with no cmap (most likely 16bpp)
  		 * cmap was set to the source palette, so no change is done.
  		 * This avoids even more ifdefs in the next stanza
  		 */
  #if defined(CONFIG_MPC823)
8f47d917c   Nikita Kiryanov   common lcd: minor...
602
  		cmap = (ushort *) &(cp->lcd_cmap[BMP_LOGO_OFFSET * sizeof(ushort)]);
39cf48048   Stelian Pop   Add ATMEL LCD driver
603
  #elif defined(CONFIG_ATMEL_LCD)
203c37b8c   Nikita Kiryanov   common lcd: simpl...
604
  		cmap = (uint *)configuration_get_cmap();
acb138689   Alessandro Rubini   lcd: make 16bpp work
605
  #else
203c37b8c   Nikita Kiryanov   common lcd: simpl...
606
  		cmap = configuration_get_cmap();
8655b6f86   wdenk   * Clean up tools/...
607
608
609
610
611
  #endif
  
  		WATCHDOG_RESET();
  
  		/* Set color map */
095407da5   Anatolij Gustschin   common/lcd.c: use...
612
  		for (i = 0; i < ARRAY_SIZE(bmp_logo_palette); ++i) {
8655b6f86   wdenk   * Clean up tools/...
613
  			ushort colreg = bmp_logo_palette[i];
39cf48048   Stelian Pop   Add ATMEL LCD driver
614
615
616
617
  #ifdef CONFIG_ATMEL_LCD
  			uint lut_entry;
  #ifdef CONFIG_ATMEL_LCD_BGR555
  			lut_entry = ((colreg & 0x000F) << 11) |
8f47d917c   Nikita Kiryanov   common lcd: minor...
618
619
  					((colreg & 0x00F0) <<  2) |
  					((colreg & 0x0F00) >>  7);
39cf48048   Stelian Pop   Add ATMEL LCD driver
620
621
  #else /* CONFIG_ATMEL_LCD_RGB565 */
  			lut_entry = ((colreg & 0x000F) << 1) |
8f47d917c   Nikita Kiryanov   common lcd: minor...
622
623
  					((colreg & 0x00F0) << 3) |
  					((colreg & 0x0F00) << 4);
39cf48048   Stelian Pop   Add ATMEL LCD driver
624
625
626
627
  #endif
  			*(cmap + BMP_LOGO_OFFSET) = lut_entry;
  			cmap++;
  #else /* !CONFIG_ATMEL_LCD */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
628
  #ifdef  CONFIG_SYS_INVERT_COLORS
8655b6f86   wdenk   * Clean up tools/...
629
630
631
632
  			*cmap++ = 0xffff - colreg;
  #else
  			*cmap++ = colreg;
  #endif
39cf48048   Stelian Pop   Add ATMEL LCD driver
633
  #endif /* CONFIG_ATMEL_LCD */
8655b6f86   wdenk   * Clean up tools/...
634
635
636
  		}
  
  		WATCHDOG_RESET();
8f47d917c   Nikita Kiryanov   common lcd: minor...
637
638
  		for (i = 0; i < BMP_LOGO_HEIGHT; ++i) {
  			memcpy(fb, bmap, BMP_LOGO_WIDTH);
8655b6f86   wdenk   * Clean up tools/...
639
  			bmap += BMP_LOGO_WIDTH;
6b035141f   Jeroen Hofstee   common/lcd: cosme...
640
  			fb += panel_info.vl_col;
8655b6f86   wdenk   * Clean up tools/...
641
642
643
  		}
  	}
  	else { /* true color mode */
acb138689   Alessandro Rubini   lcd: make 16bpp work
644
  		u16 col16;
317461c1d   Andre Renaud   Fix bitmap offset...
645
  		fb16 = (ushort *)fb;
8f47d917c   Nikita Kiryanov   common lcd: minor...
646
647
  		for (i = 0; i < BMP_LOGO_HEIGHT; ++i) {
  			for (j = 0; j < BMP_LOGO_WIDTH; j++) {
acb138689   Alessandro Rubini   lcd: make 16bpp work
648
649
650
651
652
  				col16 = bmp_logo_palette[(bmap[j]-16)];
  				fb16[j] =
  					((col16 & 0x000F) << 1) |
  					((col16 & 0x00F0) << 3) |
  					((col16 & 0x0F00) << 4);
8655b6f86   wdenk   * Clean up tools/...
653
654
655
656
657
658
659
  				}
  			bmap += BMP_LOGO_WIDTH;
  			fb16 += panel_info.vl_col;
  		}
  	}
  
  	WATCHDOG_RESET();
9a8efc460   Simon Glass   lcd: Add support ...
660
  	lcd_sync();
8655b6f86   wdenk   * Clean up tools/...
661
  }
2b5cb3d33   Anatolij Gustschin   common/lcd.c: red...
662
663
  #else
  static inline void bitmap_plot(int x, int y) {}
8655b6f86   wdenk   * Clean up tools/...
664
665
666
  #endif /* CONFIG_LCD_LOGO */
  
  /*----------------------------------------------------------------------*/
c3517f919   Jon Loeliger   common/* non-cmd*...
667
  #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
8655b6f86   wdenk   * Clean up tools/...
668
669
670
671
  /*
   * Display the BMP file located at address bmp_image.
   * Only uncompressed.
   */
1ca298ced   Matthias Weisser   Added support for...
672
673
674
  
  #ifdef CONFIG_SPLASH_SCREEN_ALIGN
  #define BMP_ALIGN_CENTER	0x7FFF
7c7e280aa   Nikita Kiryanov   common lcd: simpl...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
  
  static void splash_align_axis(int *axis, unsigned long panel_size,
  					unsigned long picture_size)
  {
  	unsigned long panel_picture_delta = panel_size - picture_size;
  	unsigned long axis_alignment;
  
  	if (*axis == BMP_ALIGN_CENTER)
  		axis_alignment = panel_picture_delta / 2;
  	else if (*axis < 0)
  		axis_alignment = panel_picture_delta + *axis + 1;
  	else
  		return;
  
  	*axis = max(0, axis_alignment);
  }
1ca298ced   Matthias Weisser   Added support for...
691
  #endif
45d7f5251   Tom Wai-Hong Tam   lcd: Implement RL...
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
  
  #ifdef CONFIG_LCD_BMP_RLE8
  
  #define BMP_RLE8_ESCAPE		0
  #define BMP_RLE8_EOL		0
  #define BMP_RLE8_EOBMP		1
  #define BMP_RLE8_DELTA		2
  
  static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap,
  				  int cnt)
  {
  	while (cnt > 0) {
  		*(*fbp)++ = cmap[*bmap++];
  		cnt--;
  	}
  }
  
  static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt)
  {
  	ushort *fb = *fbp;
  	int cnt_8copy = cnt >> 3;
  
  	cnt -= cnt_8copy << 3;
  	while (cnt_8copy > 0) {
  		*fb++ = c;
  		*fb++ = c;
  		*fb++ = c;
  		*fb++ = c;
  		*fb++ = c;
  		*fb++ = c;
  		*fb++ = c;
  		*fb++ = c;
  		cnt_8copy--;
  	}
  	while (cnt > 0) {
  		*fb++ = c;
  		cnt--;
  	}
6b035141f   Jeroen Hofstee   common/lcd: cosme...
730
  	*fbp = fb;
45d7f5251   Tom Wai-Hong Tam   lcd: Implement RL...
731
732
733
  }
  
  /*
6b035141f   Jeroen Hofstee   common/lcd: cosme...
734
   * Do not call this function directly, must be called from lcd_display_bitmap.
45d7f5251   Tom Wai-Hong Tam   lcd: Implement RL...
735
736
737
738
739
740
741
742
743
   */
  static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb,
  				    int x_off, int y_off)
  {
  	uchar *bmap;
  	ulong width, height;
  	ulong cnt, runlen;
  	int x, y;
  	int decode = 1;
dca2a1c18   Przemyslaw Marczak   common: lcd.c: fi...
744
745
746
  	width = get_unaligned_le32(&bmp->header.width);
  	height = get_unaligned_le32(&bmp->header.height);
  	bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
45d7f5251   Tom Wai-Hong Tam   lcd: Implement RL...
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  
  	x = 0;
  	y = height - 1;
  
  	while (decode) {
  		if (bmap[0] == BMP_RLE8_ESCAPE) {
  			switch (bmap[1]) {
  			case BMP_RLE8_EOL:
  				/* end of line */
  				bmap += 2;
  				x = 0;
  				y--;
  				/* 16bpix, 2-byte per pixel, width should *2 */
  				fb -= (width * 2 + lcd_line_length);
  				break;
  			case BMP_RLE8_EOBMP:
  				/* end of bitmap */
  				decode = 0;
  				break;
  			case BMP_RLE8_DELTA:
  				/* delta run */
  				x += bmap[2];
  				y -= bmap[3];
  				/* 16bpix, 2-byte per pixel, x should *2 */
  				fb = (uchar *) (lcd_base + (y + y_off - 1)
  					* lcd_line_length + (x + x_off) * 2);
  				bmap += 4;
  				break;
  			default:
  				/* unencoded run */
  				runlen = bmap[1];
  				bmap += 2;
  				if (y < height) {
  					if (x < width) {
  						if (x + runlen > width)
  							cnt = width - x;
  						else
  							cnt = runlen;
  						draw_unencoded_bitmap(
  							(ushort **)&fb,
  							bmap, cmap, cnt);
  					}
  					x += runlen;
  				}
  				bmap += runlen;
  				if (runlen & 1)
  					bmap++;
  			}
  		} else {
  			/* encoded run */
  			if (y < height) {
  				runlen = bmap[0];
  				if (x < width) {
  					/* aggregate the same code */
  					while (bmap[0] == 0xff &&
  					       bmap[2] != BMP_RLE8_ESCAPE &&
  					       bmap[1] == bmap[3]) {
  						runlen += bmap[2];
  						bmap += 2;
  					}
  					if (x + runlen > width)
  						cnt = width - x;
  					else
  						cnt = runlen;
  					draw_encoded_bitmap((ushort **)&fb,
  						cmap[bmap[1]], cnt);
  				}
  				x += runlen;
  			}
  			bmap += 2;
  		}
  	}
  }
  #endif
d23019f3d   Anatolij Gustschin   common/lcd: fix b...
821
  #if defined(CONFIG_MPC823) || defined(CONFIG_MCC200)
bfdcc65e1   Nikita Kiryanov   common lcd: simpl...
822
  #define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++)
d23019f3d   Anatolij Gustschin   common/lcd: fix b...
823
824
  #else
  #define FB_PUT_BYTE(fb, from) *(fb)++ = *(from)++
bfdcc65e1   Nikita Kiryanov   common lcd: simpl...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
  #endif
  
  #if defined(CONFIG_BMP_16BPP)
  #if defined(CONFIG_ATMEL_LCD_BGR555)
  static inline void fb_put_word(uchar **fb, uchar **from)
  {
  	*(*fb)++ = (((*from)[0] & 0x1f) << 2) | ((*from)[1] & 0x03);
  	*(*fb)++ = ((*from)[0] & 0xe0) | (((*from)[1] & 0x7c) >> 2);
  	*from += 2;
  }
  #else
  static inline void fb_put_word(uchar **fb, uchar **from)
  {
  	*(*fb)++ = *(*from)++;
  	*(*fb)++ = *(*from)++;
  }
  #endif
  #endif /* CONFIG_BMP_16BPP */
8655b6f86   wdenk   * Clean up tools/...
843
844
  int lcd_display_bitmap(ulong bmp_image, int x, int y)
  {
00cc5595a   Anatolij Gustschin   lcd: Fix compilat...
845
846
847
848
  #if !defined(CONFIG_MCC200)
  	ushort *cmap = NULL;
  #endif
  	ushort *cmap_base = NULL;
8655b6f86   wdenk   * Clean up tools/...
849
850
851
852
  	ushort i, j;
  	uchar *fb;
  	bmp_image_t *bmp=(bmp_image_t *)bmp_image;
  	uchar *bmap;
fecac46cf   Tom Wai-Hong Tam   lcd: Fix BMP deco...
853
  	ushort padded_width;
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
854
  	unsigned long width, height, byte_width;
e8143e72e   Wolfgang Denk   Add splashscreen ...
855
  	unsigned long pwidth = panel_info.vl_col;
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
856
  	unsigned colors, bpix, bmp_bpix;
8655b6f86   wdenk   * Clean up tools/...
857

6b035141f   Jeroen Hofstee   common/lcd: cosme...
858
859
  	if (!bmp || !(bmp->header.signature[0] == 'B' &&
  		bmp->header.signature[1] == 'M')) {
8f47d917c   Nikita Kiryanov   common lcd: minor...
860
861
  		printf("Error: no valid bmp image at %lx
  ", bmp_image);
8655b6f86   wdenk   * Clean up tools/...
862
  		return 1;
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
863
  	}
8655b6f86   wdenk   * Clean up tools/...
864

dca2a1c18   Przemyslaw Marczak   common: lcd.c: fi...
865
866
867
  	width = get_unaligned_le32(&bmp->header.width);
  	height = get_unaligned_le32(&bmp->header.height);
  	bmp_bpix = get_unaligned_le16(&bmp->header.bit_count);
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
868
  	colors = 1 << bmp_bpix;
8655b6f86   wdenk   * Clean up tools/...
869
870
  
  	bpix = NBITS(panel_info.vl_bpix);
6b035141f   Jeroen Hofstee   common/lcd: cosme...
871
  	if (bpix != 1 && bpix != 8 && bpix != 16 && bpix != 32) {
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
872
873
874
  		printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel
  ",
  			bpix, bmp_bpix);
8f47d917c   Nikita Kiryanov   common lcd: minor...
875

8655b6f86   wdenk   * Clean up tools/...
876
877
  		return 1;
  	}
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
878
  	/* We support displaying 8bpp BMPs on 16bpp LCDs */
dad631ccf   Nikita Kiryanov   lcd: restore abil...
879
  	if (bpix != bmp_bpix && !(bmp_bpix == 8 && bpix == 16)) {
8655b6f86   wdenk   * Clean up tools/...
880
881
  		printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel
  ",
dca2a1c18   Przemyslaw Marczak   common: lcd.c: fi...
882
  			bpix, get_unaligned_le16(&bmp->header.bit_count));
8655b6f86   wdenk   * Clean up tools/...
883
884
  		return 1;
  	}
8f47d917c   Nikita Kiryanov   common lcd: minor...
885
886
  	debug("Display-bmp: %d x %d  with %d colors
  ",
8655b6f86   wdenk   * Clean up tools/...
887
  		(int)width, (int)height, (int)colors);
f64147149   Wolfgang Denk   MCC200: Fix unini...
888
889
  #if !defined(CONFIG_MCC200)
  	/* MCC200 LCD doesn't need CMAP, supports 1bpp b&w only */
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
890
  	if (bmp_bpix == 8) {
203c37b8c   Nikita Kiryanov   common lcd: simpl...
891
  		cmap = configuration_get_cmap();
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
892
  		cmap_base = cmap;
8655b6f86   wdenk   * Clean up tools/...
893
  		/* Set color map */
8f47d917c   Nikita Kiryanov   common lcd: minor...
894
  		for (i = 0; i < colors; ++i) {
8655b6f86   wdenk   * Clean up tools/...
895
  			bmp_color_table_entry_t cte = bmp->color_table[i];
1464eff77   Mark Jackson   Fix bitmap displa...
896
  #if !defined(CONFIG_ATMEL_LCD)
8655b6f86   wdenk   * Clean up tools/...
897
898
  			ushort colreg =
  				( ((cte.red)   << 8) & 0xf800) |
59d80bf18   Wolfgang Denk   Fix computation o...
899
900
  				( ((cte.green) << 3) & 0x07e0) |
  				( ((cte.blue)  >> 3) & 0x001f) ;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
901
  #ifdef CONFIG_SYS_INVERT_COLORS
25d6712a8   wdenk   * Clean up CMC PU...
902
  			*cmap = 0xffff - colreg;
8655b6f86   wdenk   * Clean up tools/...
903
  #else
25d6712a8   wdenk   * Clean up CMC PU...
904
905
  			*cmap = colreg;
  #endif
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
906
  #if defined(CONFIG_MPC823)
25d6712a8   wdenk   * Clean up CMC PU...
907
  			cmap--;
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
908
909
  #else
  			cmap++;
8655b6f86   wdenk   * Clean up tools/...
910
  #endif
1464eff77   Mark Jackson   Fix bitmap displa...
911
912
913
  #else /* CONFIG_ATMEL_LCD */
  			lcd_setcolreg(i, cte.red, cte.green, cte.blue);
  #endif
8655b6f86   wdenk   * Clean up tools/...
914
915
  		}
  	}
f64147149   Wolfgang Denk   MCC200: Fix unini...
916
  #endif
e8143e72e   Wolfgang Denk   Add splashscreen ...
917
918
919
920
921
922
  	/*
  	 *  BMP format for Monochrome assumes that the state of a
  	 * pixel is described on a per Bit basis, not per Byte.
  	 *  So, in case of Monochrome BMP we should align widths
  	 * on a byte boundary and convert them from Bit to Byte
  	 * units.
511d0c72b   Wolfgang Denk   Coding style cleanup
923
924
  	 *  Probably, PXA250 and MPC823 process 1bpp BMP images in
  	 * their own ways, so make the converting to be MCC200
e8143e72e   Wolfgang Denk   Add splashscreen ...
925
926
927
  	 * specific.
  	 */
  #if defined(CONFIG_MCC200)
8f47d917c   Nikita Kiryanov   common lcd: minor...
928
  	if (bpix == 1) {
e8143e72e   Wolfgang Denk   Add splashscreen ...
929
930
931
932
933
  		width = ((width + 7) & ~7) >> 3;
  		x     = ((x + 7) & ~7) >> 3;
  		pwidth= ((pwidth + 7) & ~7) >> 3;
  	}
  #endif
6b035141f   Jeroen Hofstee   common/lcd: cosme...
934
  	padded_width = (width & 0x3 ? (width & ~0x3) + 4 : width);
1ca298ced   Matthias Weisser   Added support for...
935
936
  
  #ifdef CONFIG_SPLASH_SCREEN_ALIGN
7c7e280aa   Nikita Kiryanov   common lcd: simpl...
937
938
  	splash_align_axis(&x, pwidth, width);
  	splash_align_axis(&y, panel_info.vl_row, height);
1ca298ced   Matthias Weisser   Added support for...
939
  #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
8f47d917c   Nikita Kiryanov   common lcd: minor...
940
  	if ((x + width) > pwidth)
e8143e72e   Wolfgang Denk   Add splashscreen ...
941
  		width = pwidth - x;
8f47d917c   Nikita Kiryanov   common lcd: minor...
942
  	if ((y + height) > panel_info.vl_row)
8655b6f86   wdenk   * Clean up tools/...
943
  		height = panel_info.vl_row - y;
dca2a1c18   Przemyslaw Marczak   common: lcd.c: fi...
944
945
  	bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
  	fb   = (uchar *)(lcd_base +
8d46d5b18   Liu Ying   lcd: align fb wri...
946
  		(y + height - 1) * lcd_line_length + x * bpix / 8);
a303dfb0e   Mark Jackson   Add 16bpp BMP sup...
947

b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
948
  	switch (bmp_bpix) {
a303dfb0e   Mark Jackson   Add 16bpp BMP sup...
949
950
  	case 1: /* pass through */
  	case 8:
45d7f5251   Tom Wai-Hong Tam   lcd: Implement RL...
951
  #ifdef CONFIG_LCD_BMP_RLE8
dca2a1c18   Przemyslaw Marczak   common: lcd.c: fi...
952
953
  		u32 compression = get_unaligned_le32(&bmp->header.compression);
  		if (compression == BMP_BI_RLE8) {
45d7f5251   Tom Wai-Hong Tam   lcd: Implement RL...
954
955
956
957
958
959
960
961
962
  			if (bpix != 16) {
  				/* TODO implement render code for bpix != 16 */
  				printf("Error: only support 16 bpix");
  				return 1;
  			}
  			lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y);
  			break;
  		}
  #endif
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
963
964
965
966
  		if (bpix != 16)
  			byte_width = width;
  		else
  			byte_width = width * 2;
a303dfb0e   Mark Jackson   Add 16bpp BMP sup...
967
968
  		for (i = 0; i < height; ++i) {
  			WATCHDOG_RESET();
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
969
970
  			for (j = 0; j < width; j++) {
  				if (bpix != 16) {
bfdcc65e1   Nikita Kiryanov   common lcd: simpl...
971
  					FB_PUT_BYTE(fb, bmap);
b245e65ee   Guennadi Liakhovetski   LCD: support 8bpp...
972
973
974
975
976
  				} else {
  					*(uint16_t *)fb = cmap_base[*(bmap++)];
  					fb += sizeof(uint16_t) / sizeof(*fb);
  				}
  			}
fecac46cf   Tom Wai-Hong Tam   lcd: Fix BMP deco...
977
  			bmap += (padded_width - width);
6b035141f   Jeroen Hofstee   common/lcd: cosme...
978
  			fb -= byte_width + lcd_line_length;
a303dfb0e   Mark Jackson   Add 16bpp BMP sup...
979
980
981
982
983
984
985
  		}
  		break;
  
  #if defined(CONFIG_BMP_16BPP)
  	case 16:
  		for (i = 0; i < height; ++i) {
  			WATCHDOG_RESET();
bfdcc65e1   Nikita Kiryanov   common lcd: simpl...
986
987
  			for (j = 0; j < width; j++)
  				fb_put_word(&fb, &bmap);
fecac46cf   Tom Wai-Hong Tam   lcd: Fix BMP deco...
988
  			bmap += (padded_width - width) * 2;
6b035141f   Jeroen Hofstee   common/lcd: cosme...
989
  			fb -= width * 2 + lcd_line_length;
a303dfb0e   Mark Jackson   Add 16bpp BMP sup...
990
991
992
  		}
  		break;
  #endif /* CONFIG_BMP_16BPP */
fb6a9aab7   Donghwa Lee   LCD: display 32bp...
993
994
995
996
997
998
999
1000
1001
  #if defined(CONFIG_BMP_32BPP)
  	case 32:
  		for (i = 0; i < height; ++i) {
  			for (j = 0; j < width; j++) {
  				*(fb++) = *(bmap++);
  				*(fb++) = *(bmap++);
  				*(fb++) = *(bmap++);
  				*(fb++) = *(bmap++);
  			}
6b035141f   Jeroen Hofstee   common/lcd: cosme...
1002
  			fb -= lcd_line_length + width * (bpix / 8);
fb6a9aab7   Donghwa Lee   LCD: display 32bp...
1003
1004
1005
  		}
  		break;
  #endif /* CONFIG_BMP_32BPP */
a303dfb0e   Mark Jackson   Add 16bpp BMP sup...
1006
1007
1008
  	default:
  		break;
  	};
8655b6f86   wdenk   * Clean up tools/...
1009

9a8efc460   Simon Glass   lcd: Add support ...
1010
  	lcd_sync();
8f47d917c   Nikita Kiryanov   common lcd: minor...
1011
  	return 0;
8655b6f86   wdenk   * Clean up tools/...
1012
  }
c3517f919   Jon Loeliger   common/* non-cmd*...
1013
  #endif
8655b6f86   wdenk   * Clean up tools/...
1014

8f47d917c   Nikita Kiryanov   common lcd: minor...
1015
  static void *lcd_logo(void)
8655b6f86   wdenk   * Clean up tools/...
1016
  {
8655b6f86   wdenk   * Clean up tools/...
1017
1018
1019
1020
1021
1022
  #ifdef CONFIG_SPLASH_SCREEN
  	char *s;
  	ulong addr;
  	static int do_splash = 1;
  
  	if (do_splash && (s = getenv("splashimage")) != NULL) {
1ca298ced   Matthias Weisser   Added support for...
1023
  		int x = 0, y = 0;
8655b6f86   wdenk   * Clean up tools/...
1024
  		do_splash = 0;
581bb4198   Nikita Kiryanov   lcd: add option f...
1025
  		if (splash_screen_prepare())
dd4425e85   Robert Winkler   video: lcd: Add C...
1026
  			return (void *)lcd_base;
581bb4198   Nikita Kiryanov   lcd: add option f...
1027

1ca298ced   Matthias Weisser   Added support for...
1028
  		addr = simple_strtoul (s, NULL, 16);
ff8fb56b6   Anatolij Gustschin   video: consolidat...
1029
1030
  
  		splash_get_pos(&x, &y);
1ca298ced   Matthias Weisser   Added support for...
1031

d3a555edd   Nikita Kiryanov   common lcd: simpl...
1032
  		if (bmp_display(addr, x, y) == 0)
8f47d917c   Nikita Kiryanov   common lcd: minor...
1033
  			return (void *)lcd_base;
8655b6f86   wdenk   * Clean up tools/...
1034
1035
  	}
  #endif /* CONFIG_SPLASH_SCREEN */
2b5cb3d33   Anatolij Gustschin   common/lcd.c: red...
1036
  	bitmap_plot(0, 0);
8655b6f86   wdenk   * Clean up tools/...
1037

6b59e03e0   Haavard Skinnemoen   lcd: Let the boar...
1038
1039
1040
1041
1042
  #ifdef CONFIG_LCD_INFO
  	console_col = LCD_INFO_X / VIDEO_FONT_WIDTH;
  	console_row = LCD_INFO_Y / VIDEO_FONT_HEIGHT;
  	lcd_show_board_info();
  #endif /* CONFIG_LCD_INFO */
39cf48048   Stelian Pop   Add ATMEL LCD driver
1043

88804d19e   wdenk   * Patch by Detlev...
1044
  #if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
8f47d917c   Nikita Kiryanov   common lcd: minor...
1045
  	return (void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length);
8655b6f86   wdenk   * Clean up tools/...
1046
  #else
8f47d917c   Nikita Kiryanov   common lcd: minor...
1047
  	return (void *)lcd_base;
6b035141f   Jeroen Hofstee   common/lcd: cosme...
1048
  #endif /* CONFIG_LCD_LOGO && !defined(CONFIG_LCD_INFO_BELOW_LOGO) */
8655b6f86   wdenk   * Clean up tools/...
1049
  }
c08804853   Nikita Kiryanov   lcd: implement a ...
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
  #ifdef CONFIG_SPLASHIMAGE_GUARD
  static int on_splashimage(const char *name, const char *value, enum env_op op,
  	int flags)
  {
  	ulong addr;
  	int aligned;
  
  	if (op == env_op_delete)
  		return 0;
  
  	addr = simple_strtoul(value, NULL, 16);
  	/* See README.displaying-bmps */
  	aligned = (addr % 4 == 2);
  	if (!aligned) {
  		printf("Invalid splashimage value. Value must be 16 bit aligned, but not 32 bit aligned
  ");
  		return -1;
  	}
  
  	return 0;
  }
  
  U_BOOT_ENV_CALLBACK(splashimage, on_splashimage);
  #endif
395166cff   Vadim Bendebury   lcd: Provide an A...
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
  void lcd_position_cursor(unsigned col, unsigned row)
  {
  	console_col = min(col, CONSOLE_COLS - 1);
  	console_row = min(row, CONSOLE_ROWS - 1);
  }
  
  int lcd_get_pixel_width(void)
  {
  	return panel_info.vl_col;
  }
  
  int lcd_get_pixel_height(void)
  {
  	return panel_info.vl_row;
  }
  
  int lcd_get_screen_rows(void)
  {
  	return CONSOLE_ROWS;
  }
  
  int lcd_get_screen_columns(void)
  {
  	return CONSOLE_COLS;
  }
6a195d2d8   Stephen Warren   lcd: add function...
1099
1100
1101
1102
1103
1104
1105
  
  #if defined(CONFIG_LCD_DT_SIMPLEFB)
  static int lcd_dt_simplefb_configure_node(void *blob, int off)
  {
  	u32 stride;
  	fdt32_t cells[2];
  	int ret;
5af7d0f09   Stephen Warren   lcd: remove unali...
1106
  	static const char format[] =
6a195d2d8   Stephen Warren   lcd: add function...
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
  #if LCD_BPP == LCD_COLOR16
  		"r5g6b5";
  #else
  		"";
  #endif
  
  	if (!format[0])
  		return -1;
  
  	stride = panel_info.vl_col * 2;
  
  	cells[0] = cpu_to_fdt32(gd->fb_base);
  	cells[1] = cpu_to_fdt32(stride * panel_info.vl_row);
  	ret = fdt_setprop(blob, off, "reg", cells, sizeof(cells[0]) * 2);
  	if (ret < 0)
  		return -1;
  
  	cells[0] = cpu_to_fdt32(panel_info.vl_col);
  	ret = fdt_setprop(blob, off, "width", cells, sizeof(cells[0]));
  	if (ret < 0)
  		return -1;
  
  	cells[0] = cpu_to_fdt32(panel_info.vl_row);
  	ret = fdt_setprop(blob, off, "height", cells, sizeof(cells[0]));
  	if (ret < 0)
  		return -1;
  
  	cells[0] = cpu_to_fdt32(stride);
  	ret = fdt_setprop(blob, off, "stride", cells, sizeof(cells[0]));
  	if (ret < 0)
  		return -1;
  
  	ret = fdt_setprop(blob, off, "format", format, strlen(format) + 1);
  	if (ret < 0)
  		return -1;
  
  	ret = fdt_delprop(blob, off, "status");
  	if (ret < 0)
  		return -1;
  
  	return 0;
  }
  
  int lcd_dt_simplefb_add_node(void *blob)
  {
5af7d0f09   Stephen Warren   lcd: remove unali...
1152
1153
  	static const char compat[] = "simple-framebuffer";
  	static const char disabled[] = "disabled";
6a195d2d8   Stephen Warren   lcd: add function...
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
  	int off, ret;
  
  	off = fdt_add_subnode(blob, 0, "framebuffer");
  	if (off < 0)
  		return -1;
  
  	ret = fdt_setprop(blob, off, "status", disabled, sizeof(disabled));
  	if (ret < 0)
  		return -1;
  
  	ret = fdt_setprop(blob, off, "compatible", compat, sizeof(compat));
  	if (ret < 0)
  		return -1;
  
  	return lcd_dt_simplefb_configure_node(blob, off);
  }
  
  int lcd_dt_simplefb_enable_existing_node(void *blob)
  {
  	int off;
  
  	off = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer");
  	if (off < 0)
  		return -1;
  
  	return lcd_dt_simplefb_configure_node(blob, off);
  }
  #endif