]>
Commit | Line | Data |
---|---|---|
0621f6f9 SR |
1 | /* |
2 | * (C) Copyright 2003-2004 | |
3 | * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com | |
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 | #include "lcd.h" | |
25 | ||
26 | ||
27 | int palette_index; | |
28 | int palette_value; | |
29 | ||
30 | ||
31 | #ifdef CFG_LCD_ENDIAN | |
32 | void lcd_setup(int lcd, int config) | |
33 | { | |
34 | if (lcd == 0) { | |
35 | /* | |
36 | * Set endianess and reset lcd controller 0 (small) | |
37 | */ | |
38 | out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_LCD0_RST); /* set reset to low */ | |
39 | udelay(10); /* wait 10us */ | |
40 | if (config == 1) { | |
41 | out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD_ENDIAN); /* big-endian */ | |
42 | } else { | |
43 | out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_LCD_ENDIAN); /* little-endian */ | |
44 | } | |
45 | udelay(10); /* wait 10us */ | |
46 | out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD0_RST); /* set reset to high */ | |
47 | } else { | |
48 | /* | |
49 | * Set endianess and reset lcd controller 1 (big) | |
50 | */ | |
51 | out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_LCD1_RST); /* set reset to low */ | |
52 | udelay(10); /* wait 10us */ | |
53 | if (config == 1) { | |
54 | out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD_ENDIAN); /* big-endian */ | |
55 | } else { | |
56 | out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_LCD_ENDIAN); /* little-endian */ | |
57 | } | |
58 | udelay(10); /* wait 10us */ | |
59 | out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD1_RST); /* set reset to high */ | |
60 | } | |
61 | ||
62 | /* | |
63 | * CFG_LCD_ENDIAN may also be FPGA_RESET, so set inactive | |
64 | */ | |
65 | out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD_ENDIAN); /* set reset high again */ | |
66 | } | |
67 | #endif /* #ifdef CFG_LCD_ENDIAN */ | |
68 | ||
69 | ||
70 | void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count, | |
71 | uchar *logo_bmp, ulong len) | |
72 | { | |
73 | int i; | |
74 | ushort s1dReg; | |
75 | uchar s1dValue; | |
76 | uchar *ptr; | |
77 | ushort *ptr2; | |
78 | ushort val; | |
79 | unsigned char *dst; | |
80 | int x, y; | |
81 | int width, height, bpp, colors, line_size; | |
82 | int header_size; | |
83 | unsigned char *bmp; | |
84 | unsigned char r, g, b; | |
85 | BITMAPINFOHEADER *bm_info; | |
86 | int reg_byte_swap; | |
87 | ||
88 | /* | |
89 | * Detect epson | |
90 | */ | |
91 | if (lcd_reg[0] == 0x1c) { | |
92 | /* | |
93 | * Big epson detected | |
94 | */ | |
95 | reg_byte_swap = FALSE; | |
96 | palette_index = 0x1e2; | |
97 | palette_value = 0x1e4; | |
98 | puts("LCD: S1D13806"); | |
99 | } else if (lcd_reg[1] == 0x1c) { | |
100 | /* | |
101 | * Big epson detected (with register swap bug) | |
102 | */ | |
103 | reg_byte_swap = TRUE; | |
104 | palette_index = 0x1e3; | |
105 | palette_value = 0x1e5; | |
106 | puts("LCD: S1D13806S"); | |
107 | } else if (lcd_reg[0] == 0x18) { | |
108 | /* | |
109 | * Small epson detected (704) | |
110 | */ | |
111 | reg_byte_swap = FALSE; | |
112 | palette_index = 0x15; | |
113 | palette_value = 0x17; | |
114 | puts("LCD: S1D13704"); | |
115 | } else if (lcd_reg[0x10000] == 0x24) { | |
116 | /* | |
117 | * Small epson detected (705) | |
118 | */ | |
119 | reg_byte_swap = FALSE; | |
120 | palette_index = 0x15; | |
121 | palette_value = 0x17; | |
122 | lcd_reg += 0x10000; /* add offset for 705 regs */ | |
123 | puts("LCD: S1D13705"); | |
124 | } else { | |
125 | puts("LCD: No controller detected!\n"); | |
126 | return; | |
127 | } | |
128 | ||
129 | for (i = 0; i<reg_count; i++) { | |
130 | s1dReg = regs[i].Index; | |
131 | if (reg_byte_swap) { | |
132 | if ((s1dReg & 0x0001) == 0) | |
133 | s1dReg |= 0x0001; | |
134 | else | |
135 | s1dReg &= ~0x0001; | |
136 | } | |
137 | s1dValue = regs[i].Value; | |
138 | lcd_reg[s1dReg] = s1dValue; | |
efe2a4d5 | 139 | } |
0621f6f9 SR |
140 | |
141 | /* | |
142 | * Decompress bmp image | |
143 | */ | |
144 | dst = malloc(CFG_LCD_LOGO_MAX_SIZE); | |
145 | if (gunzip(dst, CFG_LCD_LOGO_MAX_SIZE, (uchar *)logo_bmp, &len) != 0) { | |
146 | return; | |
147 | } | |
148 | ||
149 | /* | |
150 | * Check for bmp mark 'BM' | |
151 | */ | |
152 | if (*(ushort *)dst != 0x424d) { | |
153 | printf("LCD: Unknown image format!\n"); | |
154 | free(dst); | |
155 | return; | |
156 | } | |
157 | ||
158 | /* | |
159 | * Get image info from bmp-header | |
160 | */ | |
161 | bm_info = (BITMAPINFOHEADER *)(dst + 14); | |
162 | bpp = LOAD_SHORT(bm_info->biBitCount); | |
163 | width = LOAD_LONG(bm_info->biWidth); | |
164 | height = LOAD_LONG(bm_info->biHeight); | |
165 | switch (bpp) { | |
166 | case 1: | |
167 | colors = 1; | |
168 | line_size = width >> 3; | |
169 | break; | |
170 | case 4: | |
171 | colors = 16; | |
172 | line_size = width >> 1; | |
173 | break; | |
174 | case 8: | |
175 | colors = 256; | |
176 | line_size = width; | |
177 | break; | |
178 | case 24: | |
179 | colors = 0; | |
180 | line_size = width * 3; | |
181 | break; | |
182 | default: | |
183 | printf("LCD: Unknown bpp (%d) im image!\n", bpp); | |
184 | free(dst); | |
185 | return; | |
186 | } | |
187 | printf(" (%d*%d, %dbpp)\n", width, height, bpp); | |
188 | ||
189 | /* | |
190 | * Write color palette | |
191 | */ | |
192 | if (colors <= 256) { | |
193 | ptr = (unsigned char *)(dst + 14 + 40); | |
194 | for (i=0; i<colors; i++) { | |
195 | b = *ptr++; | |
196 | g = *ptr++; | |
197 | r = *ptr++; | |
198 | ptr++; | |
199 | S1D_WRITE_PALETTE(lcd_reg, i, r, g, b); | |
200 | } | |
201 | } | |
202 | ||
203 | /* | |
204 | * Write bitmap data into framebuffer | |
205 | */ | |
206 | ptr = lcd_mem; | |
207 | ptr2 = (ushort *)lcd_mem; | |
208 | header_size = 14 + 40 + 4*colors; /* skip bmp header */ | |
209 | for (y=0; y<height; y++) { | |
210 | bmp = &dst[(height-1-y)*line_size + header_size]; | |
211 | if (bpp == 24) { | |
212 | for (x=0; x<width; x++) { | |
213 | /* | |
214 | * Generate epson 16bpp fb-format from 24bpp image | |
215 | */ | |
216 | b = *bmp++ >> 3; | |
217 | g = *bmp++ >> 2; | |
218 | r = *bmp++ >> 3; | |
219 | val = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f); | |
220 | *ptr2++ = val; | |
221 | } | |
222 | } else { | |
223 | for (x=0; x<line_size; x++) { | |
224 | *ptr++ = *bmp++; | |
225 | } | |
226 | } | |
227 | } | |
228 | ||
229 | free(dst); | |
230 | } |