1 /* 2 * (C) Copyright 2005-2009 3 * Jens Scharsig @ BuS Elektronik GmbH & Co. KG, <esw@bus-elektronik.de> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <bmp_layout.h> 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> 18 #include <asm/arch/at91_pio.h> 19 20 #ifndef VCBITMASK 21 #define VCBITMASK(bitno) (0x0001 << (bitno % 16)) 22 #endif 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)) 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 123 double_bws_word = (u_short *)double_bws; 124 double_bws_long = (u_long *)double_bws; 125 debug("%px %px %px\n", double_bws, double_bws_word, double_bws_long); 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 136 debug("linesize ((%ld + 15) / 8 & ~0x1) = %ld\n", 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; 144 if (vcxk_bws_long[1] == 0x55AAAA55) 145 VC4K16 = 1; 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; 254 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 { 311 while (VCXK_ACKNOWLEDGE) 312 ; 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 327 void vcxk_draw_mono(unsigned char *dataptr, unsigned long linewidth, 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 341 if ((xcnt % 8) == 7) 342 lineptr++; 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 { 361 bmp_image_t *bmp; 362 unsigned long width; 363 unsigned long height; 364 unsigned long bpp; 365 366 unsigned long lw; 367 368 unsigned long c_width; 369 unsigned long c_height; 370 unsigned char *dataptr; 371 372 bmp = (bmp_image_t *) addr; 373 if ((bmp->header.signature[0] == 'B') && 374 (bmp->header.signature[1] == 'M')) { 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) { 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); 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 */ 427