]>
Commit | Line | Data |
---|---|---|
0621f6f9 SR |
1 | /* |
2 | * (C) Copyright 2003-2004 | |
3 | * Stefan Roese, esd gmbh germany, [email protected] | |
4 | * | |
98f4a3df SR |
5 | * (C) Copyright 2005 |
6 | * Stefan Roese, DENX Software Engineering, [email protected]. | |
7 | * | |
0621f6f9 SR |
8 | * See file CREDITS for list of people who contributed to this |
9 | * project. | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU General Public License as | |
13 | * published by the Free Software Foundation; either version 2 of | |
14 | * the License, or (at your option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
22 | * along with this program; if not, write to the Free Software | |
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
24 | * MA 02111-1307 USA | |
25 | */ | |
26 | ||
77660c4b | 27 | #include "asm/io.h" |
0621f6f9 SR |
28 | #include "lcd.h" |
29 | ||
30 | ||
98f4a3df SR |
31 | extern int video_display_bitmap (ulong, int, int); |
32 | ||
33 | ||
0621f6f9 SR |
34 | int palette_index; |
35 | int palette_value; | |
98f4a3df SR |
36 | int lcd_depth; |
37 | unsigned char *glob_lcd_reg; | |
38 | unsigned char *glob_lcd_mem; | |
0621f6f9 | 39 | |
6d0f6bcf | 40 | #if defined(CONFIG_SYS_LCD_ENDIAN) |
0621f6f9 SR |
41 | void lcd_setup(int lcd, int config) |
42 | { | |
43 | if (lcd == 0) { | |
44 | /* | |
45 | * Set endianess and reset lcd controller 0 (small) | |
46 | */ | |
b9233fe5 MF |
47 | |
48 | /* set reset to low */ | |
49 | out_be32((void*)GPIO0_OR, | |
6d0f6bcf | 50 | in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD0_RST); |
0621f6f9 | 51 | udelay(10); /* wait 10us */ |
b9233fe5 MF |
52 | if (config == 1) { |
53 | /* big-endian */ | |
54 | out_be32((void*)GPIO0_OR, | |
6d0f6bcf | 55 | in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN); |
b9233fe5 MF |
56 | } else { |
57 | /* little-endian */ | |
58 | out_be32((void*)GPIO0_OR, | |
6d0f6bcf | 59 | in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD_ENDIAN); |
b9233fe5 | 60 | } |
0621f6f9 | 61 | udelay(10); /* wait 10us */ |
b9233fe5 MF |
62 | /* set reset to high */ |
63 | out_be32((void*)GPIO0_OR, | |
6d0f6bcf | 64 | in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD0_RST); |
0621f6f9 SR |
65 | } else { |
66 | /* | |
67 | * Set endianess and reset lcd controller 1 (big) | |
68 | */ | |
b9233fe5 MF |
69 | |
70 | /* set reset to low */ | |
71 | out_be32((void*)GPIO0_OR, | |
6d0f6bcf | 72 | in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD1_RST); |
0621f6f9 | 73 | udelay(10); /* wait 10us */ |
b9233fe5 MF |
74 | if (config == 1) { |
75 | /* big-endian */ | |
76 | out_be32((void*)GPIO0_OR, | |
6d0f6bcf | 77 | in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN); |
b9233fe5 MF |
78 | } else { |
79 | /* little-endian */ | |
80 | out_be32((void*)GPIO0_OR, | |
6d0f6bcf | 81 | in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD_ENDIAN); |
b9233fe5 | 82 | } |
0621f6f9 | 83 | udelay(10); /* wait 10us */ |
b9233fe5 MF |
84 | /* set reset to high */ |
85 | out_be32((void*)GPIO0_OR, | |
6d0f6bcf | 86 | in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD1_RST); |
0621f6f9 SR |
87 | } |
88 | ||
89 | /* | |
6d0f6bcf | 90 | * CONFIG_SYS_LCD_ENDIAN may also be FPGA_RESET, so set inactive |
0621f6f9 | 91 | */ |
6d0f6bcf | 92 | out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN); |
0621f6f9 | 93 | } |
6d0f6bcf | 94 | #endif /* CONFIG_SYS_LCD_ENDIAN */ |
0621f6f9 SR |
95 | |
96 | ||
b9233fe5 | 97 | int lcd_bmp(uchar *logo_bmp) |
0621f6f9 SR |
98 | { |
99 | int i; | |
0621f6f9 SR |
100 | uchar *ptr; |
101 | ushort *ptr2; | |
102 | ushort val; | |
c29ab9d7 | 103 | unsigned char *dst = NULL; |
0621f6f9 SR |
104 | int x, y; |
105 | int width, height, bpp, colors, line_size; | |
106 | int header_size; | |
107 | unsigned char *bmp; | |
108 | unsigned char r, g, b; | |
109 | BITMAPINFOHEADER *bm_info; | |
98f4a3df | 110 | ulong len; |
0621f6f9 SR |
111 | |
112 | /* | |
98f4a3df | 113 | * Check for bmp mark 'BM' |
0621f6f9 | 114 | */ |
98f4a3df | 115 | if (*(ushort *)logo_bmp != 0x424d) { |
0621f6f9 | 116 | /* |
98f4a3df | 117 | * Decompress bmp image |
0621f6f9 | 118 | */ |
6d0f6bcf JCPV |
119 | len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE; |
120 | dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE); | |
c29ab9d7 | 121 | if (dst == NULL) { |
b9233fe5 MF |
122 | printf("Error: malloc for gunzip failed!\n"); |
123 | return 1; | |
124 | } | |
6d0f6bcf | 125 | if (gunzip(dst, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, |
b9233fe5 MF |
126 | (uchar *)logo_bmp, &len) != 0) { |
127 | free(dst); | |
128 | return 1; | |
129 | } | |
6d0f6bcf | 130 | if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) { |
b9233fe5 | 131 | printf("Image could be truncated" |
6d0f6bcf | 132 | " (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n"); |
98f4a3df SR |
133 | } |
134 | ||
0621f6f9 | 135 | /* |
98f4a3df | 136 | * Check for bmp mark 'BM' |
0621f6f9 | 137 | */ |
98f4a3df SR |
138 | if (*(ushort *)dst != 0x424d) { |
139 | printf("LCD: Unknown image format!\n"); | |
140 | free(dst); | |
b9233fe5 | 141 | return 1; |
98f4a3df SR |
142 | } |
143 | } else { | |
0621f6f9 | 144 | /* |
98f4a3df | 145 | * Uncompressed BMP image, just use this pointer |
0621f6f9 | 146 | */ |
98f4a3df | 147 | dst = (uchar *)logo_bmp; |
0621f6f9 SR |
148 | } |
149 | ||
150 | /* | |
151 | * Get image info from bmp-header | |
152 | */ | |
153 | bm_info = (BITMAPINFOHEADER *)(dst + 14); | |
154 | bpp = LOAD_SHORT(bm_info->biBitCount); | |
155 | width = LOAD_LONG(bm_info->biWidth); | |
156 | height = LOAD_LONG(bm_info->biHeight); | |
157 | switch (bpp) { | |
158 | case 1: | |
159 | colors = 1; | |
160 | line_size = width >> 3; | |
161 | break; | |
162 | case 4: | |
163 | colors = 16; | |
164 | line_size = width >> 1; | |
165 | break; | |
166 | case 8: | |
167 | colors = 256; | |
168 | line_size = width; | |
169 | break; | |
170 | case 24: | |
171 | colors = 0; | |
172 | line_size = width * 3; | |
173 | break; | |
174 | default: | |
175 | printf("LCD: Unknown bpp (%d) im image!\n", bpp); | |
e174ac34 | 176 | if ((dst != NULL) && (dst != (uchar *)logo_bmp)) |
c29ab9d7 | 177 | free(dst); |
b9233fe5 | 178 | return 1; |
0621f6f9 SR |
179 | } |
180 | printf(" (%d*%d, %dbpp)\n", width, height, bpp); | |
181 | ||
182 | /* | |
183 | * Write color palette | |
184 | */ | |
98f4a3df | 185 | if ((colors <= 256) && (lcd_depth <= 8)) { |
0621f6f9 | 186 | ptr = (unsigned char *)(dst + 14 + 40); |
9ac6b6f3 | 187 | for (i = 0; i < colors; i++) { |
0621f6f9 SR |
188 | b = *ptr++; |
189 | g = *ptr++; | |
190 | r = *ptr++; | |
191 | ptr++; | |
98f4a3df | 192 | S1D_WRITE_PALETTE(glob_lcd_reg, i, r, g, b); |
0621f6f9 SR |
193 | } |
194 | } | |
195 | ||
196 | /* | |
197 | * Write bitmap data into framebuffer | |
198 | */ | |
98f4a3df SR |
199 | ptr = glob_lcd_mem; |
200 | ptr2 = (ushort *)glob_lcd_mem; | |
0621f6f9 | 201 | header_size = 14 + 40 + 4*colors; /* skip bmp header */ |
9ac6b6f3 | 202 | for (y = 0; y < height; y++) { |
0621f6f9 | 203 | bmp = &dst[(height-1-y)*line_size + header_size]; |
98f4a3df SR |
204 | if (lcd_depth == 16) { |
205 | if (bpp == 24) { | |
9ac6b6f3 | 206 | for (x = 0; x < width; x++) { |
98f4a3df | 207 | /* |
b9233fe5 MF |
208 | * Generate epson 16bpp fb-format |
209 | * from 24bpp image | |
98f4a3df SR |
210 | */ |
211 | b = *bmp++ >> 3; | |
212 | g = *bmp++ >> 2; | |
213 | r = *bmp++ >> 3; | |
b9233fe5 MF |
214 | val = ((r & 0x1f) << 11) | |
215 | ((g & 0x3f) << 5) | | |
216 | (b & 0x1f); | |
98f4a3df SR |
217 | *ptr2++ = val; |
218 | } | |
219 | } else if (bpp == 8) { | |
9ac6b6f3 | 220 | for (x = 0; x < line_size; x++) { |
98f4a3df | 221 | /* query rgb value from palette */ |
b9233fe5 | 222 | ptr = (unsigned char *)(dst + 14 + 40); |
98f4a3df SR |
223 | ptr += (*bmp++) << 2; |
224 | b = *ptr++ >> 3; | |
225 | g = *ptr++ >> 2; | |
226 | r = *ptr++ >> 3; | |
b9233fe5 MF |
227 | val = ((r & 0x1f) << 11) | |
228 | ((g & 0x3f) << 5) | | |
229 | (b & 0x1f); | |
98f4a3df SR |
230 | *ptr2++ = val; |
231 | } | |
0621f6f9 SR |
232 | } |
233 | } else { | |
9ac6b6f3 | 234 | for (x = 0; x < line_size; x++) |
0621f6f9 | 235 | *ptr++ = *bmp++; |
0621f6f9 SR |
236 | } |
237 | } | |
238 | ||
e174ac34 | 239 | if ((dst != NULL) && (dst != (uchar *)logo_bmp)) |
98f4a3df | 240 | free(dst); |
b9233fe5 | 241 | return 0; |
98f4a3df SR |
242 | } |
243 | ||
244 | ||
b9233fe5 MF |
245 | int lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count, |
246 | uchar *logo_bmp, ulong len) | |
98f4a3df SR |
247 | { |
248 | int i; | |
249 | ushort s1dReg; | |
250 | uchar s1dValue; | |
251 | int reg_byte_swap; | |
252 | ||
253 | /* | |
254 | * Detect epson | |
255 | */ | |
77660c4b MF |
256 | out_8(&lcd_reg[0], 0x00); |
257 | out_8(&lcd_reg[1], 0x00); | |
48a05a51 | 258 | |
e174ac34 | 259 | if (in_8(&lcd_reg[0]) == 0x1c) { |
98f4a3df SR |
260 | /* |
261 | * Big epson detected | |
262 | */ | |
263 | reg_byte_swap = FALSE; | |
264 | palette_index = 0x1e2; | |
265 | palette_value = 0x1e4; | |
266 | lcd_depth = 16; | |
267 | puts("LCD: S1D13806"); | |
e174ac34 | 268 | } else if (in_8(&lcd_reg[1]) == 0x1c) { |
98f4a3df SR |
269 | /* |
270 | * Big epson detected (with register swap bug) | |
271 | */ | |
272 | reg_byte_swap = TRUE; | |
273 | palette_index = 0x1e3; | |
274 | palette_value = 0x1e5; | |
275 | lcd_depth = 16; | |
276 | puts("LCD: S1D13806S"); | |
e174ac34 | 277 | } else if (in_8(&lcd_reg[0]) == 0x18) { |
98f4a3df SR |
278 | /* |
279 | * Small epson detected (704) | |
280 | */ | |
281 | reg_byte_swap = FALSE; | |
282 | palette_index = 0x15; | |
283 | palette_value = 0x17; | |
284 | lcd_depth = 8; | |
285 | puts("LCD: S1D13704"); | |
9ac6b6f3 | 286 | } else if (in_8(&lcd_reg[0x10000]) == 0x24) { |
98f4a3df SR |
287 | /* |
288 | * Small epson detected (705) | |
289 | */ | |
290 | reg_byte_swap = FALSE; | |
291 | palette_index = 0x15; | |
292 | palette_value = 0x17; | |
293 | lcd_depth = 8; | |
294 | lcd_reg += 0x10000; /* add offset for 705 regs */ | |
295 | puts("LCD: S1D13705"); | |
296 | } else { | |
b9233fe5 MF |
297 | out_8(&lcd_reg[0x1a], 0x00); |
298 | udelay(1000); | |
299 | if (in_8(&lcd_reg[1]) == 0x0c) { | |
300 | /* | |
301 | * S1D13505 detected | |
302 | */ | |
303 | reg_byte_swap = TRUE; | |
304 | palette_index = 0x25; | |
305 | palette_value = 0x27; | |
306 | lcd_depth = 16; | |
307 | ||
308 | puts("LCD: S1D13505"); | |
309 | } else { | |
310 | puts("LCD: No controller detected!\n"); | |
311 | return 1; | |
312 | } | |
98f4a3df SR |
313 | } |
314 | ||
315 | /* | |
316 | * Setup lcd controller regs | |
317 | */ | |
77660c4b | 318 | for (i = 0; i < reg_count; i++) { |
98f4a3df SR |
319 | s1dReg = regs[i].Index; |
320 | if (reg_byte_swap) { | |
321 | if ((s1dReg & 0x0001) == 0) | |
322 | s1dReg |= 0x0001; | |
323 | else | |
324 | s1dReg &= ~0x0001; | |
325 | } | |
326 | s1dValue = regs[i].Value; | |
b9233fe5 | 327 | out_8(&lcd_reg[s1dReg], s1dValue); |
98f4a3df SR |
328 | } |
329 | ||
330 | /* | |
331 | * Save reg & mem pointer for later usage (e.g. bmp command) | |
332 | */ | |
333 | glob_lcd_reg = lcd_reg; | |
334 | glob_lcd_mem = lcd_mem; | |
335 | ||
336 | /* | |
337 | * Display bmp image | |
338 | */ | |
b9233fe5 | 339 | return lcd_bmp(logo_bmp); |
0621f6f9 | 340 | } |
98f4a3df | 341 | |
98f4a3df SR |
342 | int do_esdbmp(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
343 | { | |
344 | ulong addr; | |
b9233fe5 | 345 | #ifdef CONFIG_VIDEO_SM501 |
98f4a3df | 346 | char *str; |
b9233fe5 | 347 | #endif |
98f4a3df SR |
348 | if (argc != 2) { |
349 | printf ("Usage:\n%s\n", cmdtp->usage); | |
350 | return 1; | |
351 | } | |
352 | ||
353 | addr = simple_strtoul(argv[1], NULL, 16); | |
354 | ||
b9233fe5 | 355 | #ifdef CONFIG_VIDEO_SM501 |
98f4a3df SR |
356 | str = getenv("bd_type"); |
357 | if ((strcmp(str, "ppc221") == 0) || (strcmp(str, "ppc231") == 0)) { | |
358 | /* | |
359 | * SM501 available, use standard bmp command | |
360 | */ | |
b9233fe5 | 361 | return video_display_bitmap(addr, 0, 0); |
98f4a3df SR |
362 | } else { |
363 | /* | |
364 | * No SM501 available, use esd epson bmp command | |
365 | */ | |
b9233fe5 | 366 | return lcd_bmp((uchar *)addr); |
98f4a3df | 367 | } |
b9233fe5 MF |
368 | #else |
369 | return lcd_bmp((uchar *)addr); | |
370 | #endif | |
98f4a3df SR |
371 | } |
372 | ||
373 | U_BOOT_CMD( | |
374 | esdbmp, 2, 1, do_esdbmp, | |
375 | "esdbmp - display BMP image\n", | |
376 | "<imageAddr> - display image\n" | |
377 | ); |