2 * (C) Copyright 2003-2004
3 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
6 * Stefan Roese, DENX Software Engineering, sr@denx.de.
8 * SPDX-License-Identifier: GPL-2.0+
15 extern int video_display_bitmap (ulong
, int, int);
21 unsigned char *glob_lcd_reg
;
22 unsigned char *glob_lcd_mem
;
24 #if defined(CONFIG_SYS_LCD_ENDIAN)
25 void lcd_setup(int lcd
, int config
)
29 * Set endianess and reset lcd controller 0 (small)
32 /* set reset to low */
33 out_be32((void*)GPIO0_OR
,
34 in_be32((void*)GPIO0_OR
) & ~CONFIG_SYS_LCD0_RST
);
35 udelay(10); /* wait 10us */
38 out_be32((void*)GPIO0_OR
,
39 in_be32((void*)GPIO0_OR
) | CONFIG_SYS_LCD_ENDIAN
);
42 out_be32((void*)GPIO0_OR
,
43 in_be32((void*)GPIO0_OR
) & ~CONFIG_SYS_LCD_ENDIAN
);
45 udelay(10); /* wait 10us */
46 /* set reset to high */
47 out_be32((void*)GPIO0_OR
,
48 in_be32((void*)GPIO0_OR
) | CONFIG_SYS_LCD0_RST
);
51 * Set endianess and reset lcd controller 1 (big)
54 /* set reset to low */
55 out_be32((void*)GPIO0_OR
,
56 in_be32((void*)GPIO0_OR
) & ~CONFIG_SYS_LCD1_RST
);
57 udelay(10); /* wait 10us */
60 out_be32((void*)GPIO0_OR
,
61 in_be32((void*)GPIO0_OR
) | CONFIG_SYS_LCD_ENDIAN
);
64 out_be32((void*)GPIO0_OR
,
65 in_be32((void*)GPIO0_OR
) & ~CONFIG_SYS_LCD_ENDIAN
);
67 udelay(10); /* wait 10us */
68 /* set reset to high */
69 out_be32((void*)GPIO0_OR
,
70 in_be32((void*)GPIO0_OR
) | CONFIG_SYS_LCD1_RST
);
74 * CONFIG_SYS_LCD_ENDIAN may also be FPGA_RESET, so set inactive
76 out_be32((void*)GPIO0_OR
, in_be32((void*)GPIO0_OR
) | CONFIG_SYS_LCD_ENDIAN
);
78 #endif /* CONFIG_SYS_LCD_ENDIAN */
81 int lcd_bmp(uchar
*logo_bmp
)
87 unsigned char *dst
= NULL
;
89 int width
, height
, bpp
, colors
, line_size
;
92 unsigned char r
, g
, b
;
93 BITMAPINFOHEADER
*bm_info
;
97 * Check for bmp mark 'BM'
99 if (*(ushort
*)logo_bmp
!= 0x424d) {
101 * Decompress bmp image
103 len
= CONFIG_SYS_VIDEO_LOGO_MAX_SIZE
;
104 dst
= malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE
);
106 printf("Error: malloc for gunzip failed!\n");
109 if (gunzip(dst
, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE
,
110 (uchar
*)logo_bmp
, &len
) != 0) {
114 if (len
== CONFIG_SYS_VIDEO_LOGO_MAX_SIZE
) {
115 printf("Image could be truncated"
116 " (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
120 * Check for bmp mark 'BM'
122 if (*(ushort
*)dst
!= 0x424d) {
123 printf("LCD: Unknown image format!\n");
129 * Uncompressed BMP image, just use this pointer
131 dst
= (uchar
*)logo_bmp
;
135 * Get image info from bmp-header
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
);
144 line_size
= width
>> 3;
148 line_size
= width
>> 1;
156 line_size
= width
* 3;
159 printf("LCD: Unknown bpp (%d) im image!\n", bpp
);
160 if ((dst
!= NULL
) && (dst
!= (uchar
*)logo_bmp
))
164 printf(" (%d*%d, %dbpp)\n", width
, height
, bpp
);
167 * Write color palette
169 if ((colors
<= 256) && (lcd_depth
<= 8)) {
170 ptr
= (unsigned char *)(dst
+ 14 + 40);
171 for (i
= 0; i
< colors
; i
++) {
176 S1D_WRITE_PALETTE(glob_lcd_reg
, i
, r
, g
, b
);
181 * Write bitmap data into framebuffer
184 ptr2
= (ushort
*)glob_lcd_mem
;
185 header_size
= 14 + 40 + 4*colors
; /* skip bmp header */
186 for (y
= 0; y
< height
; y
++) {
187 bmp
= &dst
[(height
-1-y
)*line_size
+ header_size
];
188 if (lcd_depth
== 16) {
190 for (x
= 0; x
< width
; x
++) {
192 * Generate epson 16bpp fb-format
198 val
= ((r
& 0x1f) << 11) |
203 } else if (bpp
== 8) {
204 for (x
= 0; x
< line_size
; x
++) {
205 /* query rgb value from palette */
206 ptr
= (unsigned char *)(dst
+ 14 + 40);
207 ptr
+= (*bmp
++) << 2;
211 val
= ((r
& 0x1f) << 11) |
218 for (x
= 0; x
< line_size
; x
++)
223 if ((dst
!= NULL
) && (dst
!= (uchar
*)logo_bmp
))
229 int lcd_init(uchar
*lcd_reg
, uchar
*lcd_mem
, S1D_REGS
*regs
, int reg_count
,
230 uchar
*logo_bmp
, ulong len
)
240 out_8(&lcd_reg
[0], 0x00);
241 out_8(&lcd_reg
[1], 0x00);
243 if (in_8(&lcd_reg
[0]) == 0x1c) {
247 reg_byte_swap
= false;
248 palette_index
= 0x1e2;
249 palette_value
= 0x1e4;
251 puts("LCD: S1D13806");
252 } else if (in_8(&lcd_reg
[1]) == 0x1c) {
254 * Big epson detected (with register swap bug)
256 reg_byte_swap
= true;
257 palette_index
= 0x1e3;
258 palette_value
= 0x1e5;
260 puts("LCD: S1D13806S");
261 } else if (in_8(&lcd_reg
[0]) == 0x18) {
263 * Small epson detected (704)
265 reg_byte_swap
= false;
266 palette_index
= 0x15;
267 palette_value
= 0x17;
269 puts("LCD: S1D13704");
270 } else if (in_8(&lcd_reg
[0x10000]) == 0x24) {
272 * Small epson detected (705)
274 reg_byte_swap
= false;
275 palette_index
= 0x15;
276 palette_value
= 0x17;
278 lcd_reg
+= 0x10000; /* add offset for 705 regs */
279 puts("LCD: S1D13705");
281 out_8(&lcd_reg
[0x1a], 0x00);
283 if (in_8(&lcd_reg
[1]) == 0x0c) {
287 reg_byte_swap
= true;
288 palette_index
= 0x25;
289 palette_value
= 0x27;
292 puts("LCD: S1D13505");
294 puts("LCD: No controller detected!\n");
300 * Setup lcd controller regs
302 for (i
= 0; i
< reg_count
; i
++) {
303 s1dReg
= regs
[i
].Index
;
305 if ((s1dReg
& 0x0001) == 0)
310 s1dValue
= regs
[i
].Value
;
311 out_8(&lcd_reg
[s1dReg
], s1dValue
);
315 * Save reg & mem pointer for later usage (e.g. bmp command)
317 glob_lcd_reg
= lcd_reg
;
318 glob_lcd_mem
= lcd_mem
;
323 return lcd_bmp(logo_bmp
);
326 int do_esdbmp(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
329 #ifdef CONFIG_VIDEO_SM501
333 return cmd_usage(cmdtp
);
335 addr
= simple_strtoul(argv
[1], NULL
, 16);
337 #ifdef CONFIG_VIDEO_SM501
338 str
= getenv("bd_type");
339 if ((strcmp(str
, "ppc221") == 0) || (strcmp(str
, "ppc231") == 0)) {
341 * SM501 available, use standard bmp command
343 return video_display_bitmap(addr
, 0, 0);
346 * No SM501 available, use esd epson bmp command
348 return lcd_bmp((uchar
*)addr
);
351 return lcd_bmp((uchar
*)addr
);
356 esdbmp
, 2, 1, do_esdbmp
,
358 "<imageAddr> - display image"