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