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