]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
50217dee JS |
2 | /* |
3 | * (C) Copyright 2005-2009 | |
4 | * Jens Scharsig @ BuS Elektronik GmbH & Co. KG, <[email protected]> | |
50217dee JS |
5 | */ |
6 | ||
7 | #include <common.h> | |
8 | #include <bmp_layout.h> | |
f7ae49fc | 9 | #include <log.h> |
50217dee JS |
10 | #include <asm/io.h> |
11 | ||
12 | vu_char *vcxk_bws = ((vu_char *) (CONFIG_SYS_VCXK_BASE)); | |
13 | vu_short *vcxk_bws_word = ((vu_short *)(CONFIG_SYS_VCXK_BASE)); | |
14 | vu_long *vcxk_bws_long = ((vu_long *) (CONFIG_SYS_VCXK_BASE)); | |
15 | ||
16 | #ifdef CONFIG_AT91RM9200 | |
17 | #include <asm/arch/hardware.h> | |
0cf0b931 JS |
18 | #include <asm/arch/at91_pio.h> |
19 | ||
50217dee JS |
20 | #ifndef VCBITMASK |
21 | #define VCBITMASK(bitno) (0x0001 << (bitno % 16)) | |
22 | #endif | |
0cf0b931 JS |
23 | at91_pio_t *pio = (at91_pio_t *) AT91_PIO_BASE; |
24 | #define VCXK_INIT_PIN(PORT, PIN, DDR, I0O1) \ | |
25 | do { \ | |
26 | writel(PIN, &pio->PORT.per); \ | |
27 | writel(PIN, &pio->PORT.DDR); \ | |
28 | writel(PIN, &pio->PORT.mddr); \ | |
29 | if (!I0O1) \ | |
30 | writel(PIN, &pio->PORT.puer); \ | |
31 | } while (0); | |
32 | ||
33 | #define VCXK_SET_PIN(PORT, PIN) writel(PIN, &pio->PORT.sodr); | |
34 | #define VCXK_CLR_PIN(PORT, PIN) writel(PIN, &pio->PORT.codr); | |
35 | ||
36 | #define VCXK_ACKNOWLEDGE \ | |
37 | (!(readl(&pio->CONFIG_SYS_VCXK_ACKNOWLEDGE_PORT.pdsr) & \ | |
38 | CONFIG_SYS_VCXK_ACKNOWLEDGE_PIN)) | |
50217dee JS |
39 | #elif defined(CONFIG_MCF52x2) |
40 | #include <asm/m5282.h> | |
41 | #ifndef VCBITMASK | |
42 | #define VCBITMASK(bitno) (0x8000 >> (bitno % 16)) | |
43 | #endif | |
44 | ||
45 | #define VCXK_INIT_PIN(PORT, PIN, DDR, I0O1) \ | |
46 | if (I0O1) DDR |= PIN; else DDR &= ~PIN; | |
47 | ||
48 | #define VCXK_SET_PIN(PORT, PIN) PORT |= PIN; | |
49 | #define VCXK_CLR_PIN(PORT, PIN) PORT &= ~PIN; | |
50 | ||
51 | #define VCXK_ACKNOWLEDGE \ | |
52 | (!(CONFIG_SYS_VCXK_ACKNOWLEDGE_PORT & \ | |
53 | CONFIG_SYS_VCXK_ACKNOWLEDGE_PIN)) | |
54 | ||
55 | #else | |
56 | #error no vcxk support for selected ARCH | |
57 | #endif | |
58 | ||
59 | #define VCXK_DISABLE\ | |
60 | VCXK_SET_PIN(CONFIG_SYS_VCXK_ENABLE_PORT, CONFIG_SYS_VCXK_ENABLE_PIN) | |
61 | #define VCXK_ENABLE\ | |
62 | VCXK_CLR_PIN(CONFIG_SYS_VCXK_ENABLE_PORT, CONFIG_SYS_VCXK_ENABLE_PIN) | |
63 | ||
64 | #ifndef CONFIG_SYS_VCXK_DOUBLEBUFFERED | |
65 | #define VCXK_BWS(x, data) vcxk_bws[x] = data; | |
66 | #define VCXK_BWS_WORD_SET(x, mask) vcxk_bws_word[x] |= mask; | |
67 | #define VCXK_BWS_WORD_CLEAR(x, mask) vcxk_bws_word[x] &= ~mask; | |
68 | #define VCXK_BWS_LONG(x, data) vcxk_bws_long[x] = data; | |
69 | #else | |
70 | u_char double_bws[16384]; | |
71 | u_short *double_bws_word; | |
72 | u_long *double_bws_long; | |
73 | #define VCXK_BWS(x,data) \ | |
74 | double_bws[x] = data; vcxk_bws[x] = data; | |
75 | #define VCXK_BWS_WORD_SET(x,mask) \ | |
76 | double_bws_word[x] |= mask; \ | |
77 | vcxk_bws_word[x] = double_bws_word[x]; | |
78 | #define VCXK_BWS_WORD_CLEAR(x,mask) \ | |
79 | double_bws_word[x] &= ~mask; \ | |
80 | vcxk_bws_word[x] = double_bws_word[x]; | |
81 | #define VCXK_BWS_LONG(x,data) \ | |
82 | double_bws_long[x] = data; vcxk_bws_long[x] = data; | |
83 | #endif | |
84 | ||
85 | #define VC4K16_Bright1 vcxk_bws_word[0x20004 / 2] | |
86 | #define VC4K16_Bright2 vcxk_bws_word[0x20006 / 2] | |
87 | #define VC2K_Bright vcxk_bws[0x8000] | |
88 | #define VC8K_BrightH vcxk_bws[0xC000] | |
89 | #define VC8K_BrightL vcxk_bws[0xC001] | |
90 | ||
91 | vu_char VC4K16; | |
92 | ||
93 | u_long display_width; | |
94 | u_long display_height; | |
95 | u_long display_bwidth; | |
96 | ||
97 | ulong search_vcxk_driver(void); | |
98 | void vcxk_cls(void); | |
99 | void vcxk_setbrightness(unsigned int side, short brightness); | |
100 | int vcxk_request(void); | |
101 | int vcxk_acknowledge_wait(void); | |
102 | void vcxk_clear(void); | |
103 | ||
104 | /* | |
105 | ****f* bus_vcxk/vcxk_init | |
106 | * FUNCTION | |
107 | * initialalize Video Controller | |
108 | * PARAMETERS | |
109 | * width visible display width in pixel | |
110 | * height visible display height in pixel | |
111 | *** | |
112 | */ | |
113 | ||
114 | int vcxk_init(unsigned long width, unsigned long height) | |
115 | { | |
116 | #ifdef CONFIG_SYS_VCXK_RESET_PORT | |
117 | VCXK_INIT_PIN(CONFIG_SYS_VCXK_RESET_PORT, | |
118 | CONFIG_SYS_VCXK_RESET_PIN, CONFIG_SYS_VCXK_RESET_DDR, 1) | |
119 | VCXK_SET_PIN(CONFIG_SYS_VCXK_RESET_PORT, CONFIG_SYS_VCXK_RESET_PIN); | |
120 | #endif | |
121 | ||
122 | #ifdef CONFIG_SYS_VCXK_DOUBLEBUFFERED | |
04538cdb | 123 | double_bws_word = (u_short *)double_bws; |
50217dee | 124 | double_bws_long = (u_long *)double_bws; |
4a1921eb | 125 | debug("%px %px %px\n", double_bws, double_bws_word, double_bws_long); |
50217dee JS |
126 | #endif |
127 | display_width = width; | |
128 | display_height = height; | |
129 | #if (CONFIG_SYS_VCXK_DEFAULT_LINEALIGN == 4) | |
130 | display_bwidth = ((width + 31) / 8) & ~0x3; | |
131 | #elif (CONFIG_SYS_VCXK_DEFAULT_LINEALIGN == 2) | |
132 | display_bwidth = ((width + 15) / 8) & ~0x1; | |
133 | #else | |
134 | #error CONFIG_SYS_VCXK_DEFAULT_LINEALIGN is invalid | |
135 | #endif | |
458f4381 | 136 | debug("linesize ((%ld + 15) / 8 & ~0x1) = %ld\n", |
50217dee JS |
137 | display_width, display_bwidth); |
138 | ||
139 | #ifdef CONFIG_SYS_VCXK_AUTODETECT | |
140 | VC4K16 = 0; | |
141 | vcxk_bws_long[1] = 0x0; | |
142 | vcxk_bws_long[1] = 0x55AAAA55; | |
143 | vcxk_bws_long[5] = 0x0; | |
04538cdb AG |
144 | if (vcxk_bws_long[1] == 0x55AAAA55) |
145 | VC4K16 = 1; | |
50217dee JS |
146 | #else |
147 | VC4K16 = 1; | |
148 | debug("No autodetect: use vc4k\n"); | |
149 | #endif | |
150 | ||
151 | VCXK_INIT_PIN(CONFIG_SYS_VCXK_INVERT_PORT, | |
152 | CONFIG_SYS_VCXK_INVERT_PIN, CONFIG_SYS_VCXK_INVERT_DDR, 1) | |
153 | VCXK_SET_PIN(CONFIG_SYS_VCXK_INVERT_PORT, CONFIG_SYS_VCXK_INVERT_PIN) | |
154 | ||
155 | VCXK_SET_PIN(CONFIG_SYS_VCXK_REQUEST_PORT, CONFIG_SYS_VCXK_REQUEST_PIN); | |
156 | VCXK_INIT_PIN(CONFIG_SYS_VCXK_REQUEST_PORT, | |
157 | CONFIG_SYS_VCXK_REQUEST_PIN, CONFIG_SYS_VCXK_REQUEST_DDR, 1) | |
158 | ||
159 | VCXK_INIT_PIN(CONFIG_SYS_VCXK_ACKNOWLEDGE_PORT, | |
160 | CONFIG_SYS_VCXK_ACKNOWLEDGE_PIN, | |
161 | CONFIG_SYS_VCXK_ACKNOWLEDGE_DDR, 0) | |
162 | ||
163 | VCXK_DISABLE; | |
164 | VCXK_INIT_PIN(CONFIG_SYS_VCXK_ENABLE_PORT, | |
165 | CONFIG_SYS_VCXK_ENABLE_PIN, CONFIG_SYS_VCXK_ENABLE_DDR, 1) | |
166 | ||
167 | vcxk_cls(); | |
168 | vcxk_cls(); /* clear second/hidden page */ | |
169 | ||
170 | vcxk_setbrightness(3, 1000); | |
171 | VCXK_ENABLE; | |
172 | return 1; | |
173 | } | |
174 | ||
175 | /* | |
176 | ****f* bus_vcxk/vcxk_setpixel | |
177 | * FUNCTION | |
178 | * set the pixel[x,y] with the given color | |
179 | * PARAMETER | |
180 | * x pixel colum | |
181 | * y pixel row | |
182 | * color <0x40 off/black | |
183 | * >0x40 on | |
184 | *** | |
185 | */ | |
186 | ||
187 | void vcxk_setpixel(int x, int y, unsigned long color) | |
188 | { | |
189 | vu_short dataptr; | |
190 | ||
191 | if ((x < display_width) && (y < display_height)) { | |
192 | dataptr = ((x / 16)) + (y * (display_bwidth >> 1)); | |
193 | ||
194 | color = ((color >> 16) & 0xFF) | | |
195 | ((color >> 8) & 0xFF) | (color & 0xFF); | |
196 | ||
197 | if (color > 0x40) { | |
198 | VCXK_BWS_WORD_SET(dataptr, VCBITMASK(x)); | |
199 | } else { | |
200 | VCXK_BWS_WORD_CLEAR(dataptr, VCBITMASK(x)); | |
201 | } | |
202 | } | |
203 | } | |
204 | ||
205 | /* | |
206 | ****f* bus_vcxk/vcxk_loadimage | |
207 | * FUNCTION | |
208 | * copies a binary image to display memory | |
209 | *** | |
210 | */ | |
211 | ||
212 | void vcxk_loadimage(ulong source) | |
213 | { | |
214 | int cnt; | |
215 | vcxk_acknowledge_wait(); | |
216 | if (VC4K16) { | |
217 | for (cnt = 0; cnt < (16384 / 4); cnt++) { | |
218 | VCXK_BWS_LONG(cnt, (*(ulong *) source)); | |
219 | source = source + 4; | |
220 | } | |
221 | } else { | |
222 | for (cnt = 0; cnt < 16384; cnt++) { | |
223 | VCXK_BWS_LONG(cnt*2, (*(vu_char *) source)); | |
224 | source++; | |
225 | } | |
226 | } | |
227 | vcxk_request(); | |
228 | } | |
229 | ||
230 | /* | |
231 | ****f* bus_vcxk/vcxk_cls | |
232 | * FUNCTION | |
233 | * clear the display | |
234 | *** | |
235 | */ | |
236 | ||
237 | void vcxk_cls(void) | |
238 | { | |
239 | vcxk_acknowledge_wait(); | |
240 | vcxk_clear(); | |
241 | vcxk_request(); | |
242 | } | |
243 | ||
244 | /* | |
245 | ****f* bus_vcxk/vcxk_clear(void) | |
246 | * FUNCTION | |
247 | * clear the display memory | |
248 | *** | |
249 | */ | |
250 | ||
251 | void vcxk_clear(void) | |
252 | { | |
253 | int cnt; | |
04538cdb | 254 | |
50217dee JS |
255 | for (cnt = 0; cnt < (16384 / 4); cnt++) { |
256 | VCXK_BWS_LONG(cnt, 0) | |
257 | } | |
258 | } | |
259 | ||
260 | /* | |
261 | ****f* bus_vcxk/vcxk_setbrightness | |
262 | * FUNCTION | |
263 | * set the display brightness | |
264 | * PARAMETER | |
265 | * side 1 set front side brightness | |
266 | * 2 set back side brightness | |
267 | * 3 set brightness for both sides | |
268 | * brightness 0..1000 | |
269 | *** | |
270 | */ | |
271 | ||
272 | void vcxk_setbrightness(unsigned int side, short brightness) | |
273 | { | |
274 | if (VC4K16) { | |
275 | if ((side == 0) || (side & 0x1)) | |
276 | VC4K16_Bright1 = brightness + 23; | |
277 | if ((side == 0) || (side & 0x2)) | |
278 | VC4K16_Bright2 = brightness + 23; | |
279 | } else { | |
280 | VC2K_Bright = (brightness >> 4) + 2; | |
281 | VC8K_BrightH = (brightness + 23) >> 8; | |
282 | VC8K_BrightL = (brightness + 23) & 0xFF; | |
283 | } | |
284 | } | |
285 | ||
286 | /* | |
287 | ****f* bus_vcxk/vcxk_request | |
288 | * FUNCTION | |
289 | * requests viewing of display memory | |
290 | *** | |
291 | */ | |
292 | ||
293 | int vcxk_request(void) | |
294 | { | |
295 | VCXK_CLR_PIN(CONFIG_SYS_VCXK_REQUEST_PORT, | |
296 | CONFIG_SYS_VCXK_REQUEST_PIN) | |
297 | VCXK_SET_PIN(CONFIG_SYS_VCXK_REQUEST_PORT, | |
298 | CONFIG_SYS_VCXK_REQUEST_PIN); | |
299 | return 1; | |
300 | } | |
301 | ||
302 | /* | |
303 | ****f* bus_vcxk/vcxk_acknowledge_wait | |
304 | * FUNCTION | |
305 | * wait for acknowledge viewing requests | |
306 | *** | |
307 | */ | |
308 | ||
309 | int vcxk_acknowledge_wait(void) | |
310 | { | |
04538cdb AG |
311 | while (VCXK_ACKNOWLEDGE) |
312 | ; | |
50217dee JS |
313 | return 1; |
314 | } | |
315 | ||
316 | /* | |
317 | ****f* bus_vcxk/vcxk_draw_mono | |
318 | * FUNCTION | |
319 | * copies a monochrom bitmap (BMP-Format) from given memory | |
320 | * PARAMETER | |
321 | * dataptr pointer to bitmap | |
322 | * x output bitmap @ columne | |
323 | * y output bitmap @ row | |
324 | *** | |
325 | */ | |
326 | ||
04538cdb | 327 | void vcxk_draw_mono(unsigned char *dataptr, unsigned long linewidth, |
50217dee JS |
328 | unsigned long cp_width, unsigned long cp_height) |
329 | { | |
330 | unsigned char *lineptr; | |
331 | unsigned long xcnt, ycnt; | |
332 | ||
333 | for (ycnt = cp_height; ycnt > 0; ycnt--) { | |
334 | lineptr = dataptr; | |
335 | for (xcnt = 0; xcnt < cp_width; xcnt++) { | |
336 | if ((*lineptr << (xcnt % 8)) & 0x80) | |
337 | vcxk_setpixel(xcnt, ycnt - 1, 0xFFFFFF); | |
338 | else | |
339 | vcxk_setpixel(xcnt, ycnt-1, 0); | |
340 | ||
04538cdb AG |
341 | if ((xcnt % 8) == 7) |
342 | lineptr++; | |
50217dee JS |
343 | } /* endfor xcnt */ |
344 | dataptr = dataptr + linewidth; | |
345 | } /* endfor ycnt */ | |
346 | } | |
347 | ||
348 | /* | |
349 | ****f* bus_vcxk/vcxk_display_bitmap | |
350 | * FUNCTION | |
351 | * copies a bitmap (BMP-Format) to the given position | |
352 | * PARAMETER | |
353 | * addr pointer to bitmap | |
354 | * x output bitmap @ columne | |
355 | * y output bitmap @ row | |
356 | *** | |
357 | */ | |
358 | ||
359 | int vcxk_display_bitmap(ulong addr, int x, int y) | |
360 | { | |
1c3dbe56 | 361 | struct bmp_image *bmp; |
50217dee JS |
362 | unsigned long width; |
363 | unsigned long height; | |
364 | unsigned long bpp; | |
50217dee JS |
365 | |
366 | unsigned long lw; | |
367 | ||
368 | unsigned long c_width; | |
369 | unsigned long c_height; | |
370 | unsigned char *dataptr; | |
50217dee | 371 | |
1c3dbe56 | 372 | bmp = (struct bmp_image *)addr; |
50217dee JS |
373 | if ((bmp->header.signature[0] == 'B') && |
374 | (bmp->header.signature[1] == 'M')) { | |
50217dee JS |
375 | width = le32_to_cpu(bmp->header.width); |
376 | height = le32_to_cpu(bmp->header.height); | |
377 | bpp = le16_to_cpu(bmp->header.bit_count); | |
378 | ||
379 | dataptr = (unsigned char *) bmp + | |
380 | le32_to_cpu(bmp->header.data_offset); | |
381 | ||
382 | if (display_width < (width + x)) | |
383 | c_width = display_width - x; | |
384 | else | |
385 | c_width = width; | |
386 | if (display_height < (height + y)) | |
387 | c_height = display_height - y; | |
388 | else | |
389 | c_height = height; | |
390 | ||
391 | lw = (((width + 7) / 8) + 3) & ~0x3; | |
392 | ||
393 | if (c_height < height) | |
394 | dataptr = dataptr + lw * (height - c_height); | |
395 | switch (bpp) { | |
04538cdb AG |
396 | case 1: |
397 | vcxk_draw_mono(dataptr, lw, c_width, c_height); | |
398 | break; | |
399 | default: | |
400 | printf("Error: %ld bit per pixel " | |
401 | "not supported by VCxK\n", bpp); | |
50217dee JS |
402 | return 0; |
403 | } | |
404 | } else { | |
405 | printf("Error: no valid bmp at %lx\n", (ulong) bmp); | |
406 | return 0; | |
407 | } | |
408 | return 1; | |
409 | } | |
410 | ||
411 | /* | |
412 | ****f* bus_vcxk/video_display_bitmap | |
413 | *** | |
414 | */ | |
415 | ||
416 | int video_display_bitmap(ulong addr, int x, int y) | |
417 | { | |
418 | vcxk_acknowledge_wait(); | |
419 | if (vcxk_display_bitmap(addr, x, y)) { | |
420 | vcxk_request(); | |
421 | return 0; | |
422 | } | |
423 | return 1; | |
424 | } | |
425 | ||
426 | /* EOF */ |