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