1 /* 2 * Common LCD routines 3 * 4 * (C) Copyright 2001-2002 5 * Wolfgang Denk, DENX Software Engineering -- wd@denx.de 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 /* #define DEBUG */ 11 #include <config.h> 12 #include <common.h> 13 #include <command.h> 14 #include <env_callback.h> 15 #include <linux/types.h> 16 #include <stdio_dev.h> 17 #include <lcd.h> 18 #include <watchdog.h> 19 #include <asm/unaligned.h> 20 #include <splash.h> 21 #include <asm/io.h> 22 #include <asm/unaligned.h> 23 #include <video_font.h> 24 25 #ifdef CONFIG_LCD_LOGO 26 #include <bmp_logo.h> 27 #include <bmp_logo_data.h> 28 #if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET) && (LCD_BPP != LCD_COLOR16) 29 #error Default Color Map overlaps with Logo Color Map 30 #endif 31 #endif 32 33 #ifdef CONFIG_SANDBOX 34 #include <asm/sdl.h> 35 #endif 36 37 #ifndef CONFIG_LCD_ALIGNMENT 38 #define CONFIG_LCD_ALIGNMENT PAGE_SIZE 39 #endif 40 41 #if (LCD_BPP != LCD_COLOR8) && (LCD_BPP != LCD_COLOR16) && \ 42 (LCD_BPP != LCD_COLOR32) 43 #error Unsupported LCD BPP. 44 #endif 45 46 DECLARE_GLOBAL_DATA_PTR; 47 48 static int lcd_init(void *lcdbase); 49 static void lcd_logo(void); 50 static void lcd_setfgcolor(int color); 51 static void lcd_setbgcolor(int color); 52 53 static int lcd_color_fg; 54 static int lcd_color_bg; 55 int lcd_line_length; 56 char lcd_is_enabled = 0; 57 static void *lcd_base; /* Start of framebuffer memory */ 58 static char lcd_flush_dcache; /* 1 to flush dcache after each lcd update */ 59 60 /* Flush LCD activity to the caches */ 61 void lcd_sync(void) 62 { 63 /* 64 * flush_dcache_range() is declared in common.h but it seems that some 65 * architectures do not actually implement it. Is there a way to find 66 * out whether it exists? For now, ARM is safe. 67 */ 68 #if defined(CONFIG_ARM) && !defined(CONFIG_SYS_DCACHE_OFF) 69 int line_length; 70 71 if (lcd_flush_dcache) 72 flush_dcache_range((u32)lcd_base, 73 (u32)(lcd_base + lcd_get_size(&line_length))); 74 #elif defined(CONFIG_SANDBOX) && defined(CONFIG_VIDEO_SANDBOX_SDL) 75 static ulong last_sync; 76 77 if (get_timer(last_sync) > 10) { 78 sandbox_sdl_sync(lcd_base); 79 last_sync = get_timer(0); 80 } 81 #endif 82 } 83 84 void lcd_set_flush_dcache(int flush) 85 { 86 lcd_flush_dcache = (flush != 0); 87 } 88 89 static void lcd_stub_putc(struct stdio_dev *dev, const char c) 90 { 91 lcd_putc(c); 92 } 93 94 static void lcd_stub_puts(struct stdio_dev *dev, const char *s) 95 { 96 lcd_puts(s); 97 } 98 99 /* Small utility to check that you got the colours right */ 100 #ifdef LCD_TEST_PATTERN 101 102 #define N_BLK_VERT 2 103 #define N_BLK_HOR 3 104 105 static int test_colors[N_BLK_HOR * N_BLK_VERT] = { 106 CONSOLE_COLOR_RED, CONSOLE_COLOR_GREEN, CONSOLE_COLOR_YELLOW, 107 CONSOLE_COLOR_BLUE, CONSOLE_COLOR_MAGENTA, CONSOLE_COLOR_CYAN, 108 }; 109 110 static void test_pattern(void) 111 { 112 ushort v_max = panel_info.vl_row; 113 ushort h_max = panel_info.vl_col; 114 ushort v_step = (v_max + N_BLK_VERT - 1) / N_BLK_VERT; 115 ushort h_step = (h_max + N_BLK_HOR - 1) / N_BLK_HOR; 116 ushort v, h; 117 uchar *pix = (uchar *)lcd_base; 118 119 printf("[LCD] Test Pattern: %d x %d [%d x %d]\n", 120 h_max, v_max, h_step, v_step); 121 122 /* WARNING: Code silently assumes 8bit/pixel */ 123 for (v = 0; v < v_max; ++v) { 124 uchar iy = v / v_step; 125 for (h = 0; h < h_max; ++h) { 126 uchar ix = N_BLK_HOR * iy + h / h_step; 127 *pix++ = test_colors[ix]; 128 } 129 } 130 } 131 #endif /* LCD_TEST_PATTERN */ 132 133 /* 134 * With most lcd drivers the line length is set up 135 * by calculating it from panel_info parameters. Some 136 * drivers need to calculate the line length differently, 137 * so make the function weak to allow overriding it. 138 */ 139 __weak int lcd_get_size(int *line_length) 140 { 141 *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; 142 return *line_length * panel_info.vl_row; 143 } 144 145 int drv_lcd_init(void) 146 { 147 struct stdio_dev lcddev; 148 int rc; 149 150 lcd_base = map_sysmem(gd->fb_base, 0); 151 152 lcd_init(lcd_base); 153 154 /* Device initialization */ 155 memset(&lcddev, 0, sizeof(lcddev)); 156 157 strcpy(lcddev.name, "lcd"); 158 lcddev.ext = 0; /* No extensions */ 159 lcddev.flags = DEV_FLAGS_OUTPUT; /* Output only */ 160 lcddev.putc = lcd_stub_putc; /* 'putc' function */ 161 lcddev.puts = lcd_stub_puts; /* 'puts' function */ 162 163 rc = stdio_register(&lcddev); 164 165 return (rc == 0) ? 1 : rc; 166 } 167 168 void lcd_clear(void) 169 { 170 int bg_color; 171 char *s; 172 ulong addr; 173 static int do_splash = 1; 174 #if LCD_BPP == LCD_COLOR8 175 /* Setting the palette */ 176 lcd_setcolreg(CONSOLE_COLOR_BLACK, 0, 0, 0); 177 lcd_setcolreg(CONSOLE_COLOR_RED, 0xFF, 0, 0); 178 lcd_setcolreg(CONSOLE_COLOR_GREEN, 0, 0xFF, 0); 179 lcd_setcolreg(CONSOLE_COLOR_YELLOW, 0xFF, 0xFF, 0); 180 lcd_setcolreg(CONSOLE_COLOR_BLUE, 0, 0, 0xFF); 181 lcd_setcolreg(CONSOLE_COLOR_MAGENTA, 0xFF, 0, 0xFF); 182 lcd_setcolreg(CONSOLE_COLOR_CYAN, 0, 0xFF, 0xFF); 183 lcd_setcolreg(CONSOLE_COLOR_GREY, 0xAA, 0xAA, 0xAA); 184 lcd_setcolreg(CONSOLE_COLOR_WHITE, 0xFF, 0xFF, 0xFF); 185 #endif 186 187 #ifndef CONFIG_SYS_WHITE_ON_BLACK 188 lcd_setfgcolor(CONSOLE_COLOR_BLACK); 189 lcd_setbgcolor(CONSOLE_COLOR_WHITE); 190 bg_color = CONSOLE_COLOR_WHITE; 191 #else 192 lcd_setfgcolor(CONSOLE_COLOR_WHITE); 193 lcd_setbgcolor(CONSOLE_COLOR_BLACK); 194 bg_color = CONSOLE_COLOR_BLACK; 195 #endif /* CONFIG_SYS_WHITE_ON_BLACK */ 196 197 #ifdef LCD_TEST_PATTERN 198 test_pattern(); 199 #else 200 /* set framebuffer to background color */ 201 #if (LCD_BPP != LCD_COLOR32) 202 memset((char *)lcd_base, bg_color, lcd_line_length * panel_info.vl_row); 203 #else 204 u32 *ppix = lcd_base; 205 u32 i; 206 for (i = 0; 207 i < (lcd_line_length * panel_info.vl_row)/NBYTES(panel_info.vl_bpix); 208 i++) { 209 *ppix++ = bg_color; 210 } 211 #endif 212 #endif 213 /* setup text-console */ 214 debug("[LCD] setting up console...\n"); 215 lcd_init_console(lcd_base, 216 panel_info.vl_col, 217 panel_info.vl_row, 218 panel_info.vl_rot); 219 /* Paint the logo and retrieve LCD base address */ 220 debug("[LCD] Drawing the logo...\n"); 221 if (do_splash) { 222 s = getenv("splashimage"); 223 if (s) { 224 do_splash = 0; 225 addr = simple_strtoul(s, NULL, 16); 226 if (lcd_splash(addr) == 0) { 227 lcd_sync(); 228 return; 229 } 230 } 231 } 232 233 lcd_logo(); 234 #if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO) 235 addr = (ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length; 236 lcd_init_console((void *)addr, panel_info.vl_row, 237 panel_info.vl_col, panel_info.vl_rot); 238 #endif 239 lcd_sync(); 240 } 241 242 static int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc, 243 char *const argv[]) 244 { 245 lcd_clear(); 246 return 0; 247 } 248 U_BOOT_CMD(cls, 1, 1, do_lcd_clear, "clear screen", ""); 249 250 static int lcd_init(void *lcdbase) 251 { 252 debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase); 253 lcd_ctrl_init(lcdbase); 254 255 /* 256 * lcd_ctrl_init() of some drivers (i.e. bcm2835 on rpi) ignores 257 * the 'lcdbase' argument and uses custom lcd base address 258 * by setting up gd->fb_base. Check for this condition and fixup 259 * 'lcd_base' address. 260 */ 261 if (map_to_sysmem(lcdbase) != gd->fb_base) 262 lcd_base = map_sysmem(gd->fb_base, 0); 263 264 debug("[LCD] Using LCD frambuffer at %p\n", lcd_base); 265 266 lcd_get_size(&lcd_line_length); 267 lcd_is_enabled = 1; 268 lcd_clear(); 269 lcd_enable(); 270 271 /* Initialize the console */ 272 lcd_set_col(0); 273 #ifdef CONFIG_LCD_INFO_BELOW_LOGO 274 lcd_set_row(7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT); 275 #else 276 lcd_set_row(1); /* leave 1 blank line below logo */ 277 #endif 278 279 return 0; 280 } 281 282 /* 283 * This is called early in the system initialization to grab memory 284 * for the LCD controller. 285 * Returns new address for monitor, after reserving LCD buffer memory 286 * 287 * Note that this is running from ROM, so no write access to global data. 288 */ 289 ulong lcd_setmem(ulong addr) 290 { 291 ulong size; 292 int line_length; 293 294 debug("LCD panel info: %d x %d, %d bit/pix\n", panel_info.vl_col, 295 panel_info.vl_row, NBITS(panel_info.vl_bpix)); 296 297 size = lcd_get_size(&line_length); 298 299 /* Round up to nearest full page, or MMU section if defined */ 300 size = ALIGN(size, CONFIG_LCD_ALIGNMENT); 301 addr = ALIGN(addr - CONFIG_LCD_ALIGNMENT + 1, CONFIG_LCD_ALIGNMENT); 302 303 /* Allocate pages for the frame buffer. */ 304 addr -= size; 305 306 debug("Reserving %ldk for LCD Framebuffer at: %08lx\n", 307 size >> 10, addr); 308 309 return addr; 310 } 311 312 static void lcd_setfgcolor(int color) 313 { 314 lcd_color_fg = color; 315 } 316 317 int lcd_getfgcolor(void) 318 { 319 return lcd_color_fg; 320 } 321 322 static void lcd_setbgcolor(int color) 323 { 324 lcd_color_bg = color; 325 } 326 327 int lcd_getbgcolor(void) 328 { 329 return lcd_color_bg; 330 } 331 332 #ifdef CONFIG_LCD_LOGO 333 __weak void lcd_logo_set_cmap(void) 334 { 335 int i; 336 ushort *cmap = configuration_get_cmap(); 337 338 for (i = 0; i < ARRAY_SIZE(bmp_logo_palette); ++i) 339 *cmap++ = bmp_logo_palette[i]; 340 } 341 342 void lcd_logo_plot(int x, int y) 343 { 344 ushort i, j; 345 uchar *bmap = &bmp_logo_bitmap[0]; 346 unsigned bpix = NBITS(panel_info.vl_bpix); 347 uchar *fb = (uchar *)(lcd_base + y * lcd_line_length + x * bpix / 8); 348 ushort *fb16; 349 350 debug("Logo: width %d height %d colors %d\n", 351 BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS); 352 353 if (bpix < 12) { 354 WATCHDOG_RESET(); 355 lcd_logo_set_cmap(); 356 WATCHDOG_RESET(); 357 358 for (i = 0; i < BMP_LOGO_HEIGHT; ++i) { 359 memcpy(fb, bmap, BMP_LOGO_WIDTH); 360 bmap += BMP_LOGO_WIDTH; 361 fb += panel_info.vl_col; 362 } 363 } 364 else { /* true color mode */ 365 u16 col16; 366 fb16 = (ushort *)fb; 367 for (i = 0; i < BMP_LOGO_HEIGHT; ++i) { 368 for (j = 0; j < BMP_LOGO_WIDTH; j++) { 369 col16 = bmp_logo_palette[(bmap[j]-16)]; 370 fb16[j] = 371 ((col16 & 0x000F) << 1) | 372 ((col16 & 0x00F0) << 3) | 373 ((col16 & 0x0F00) << 4); 374 } 375 bmap += BMP_LOGO_WIDTH; 376 fb16 += panel_info.vl_col; 377 } 378 } 379 380 WATCHDOG_RESET(); 381 lcd_sync(); 382 } 383 #else 384 static inline void lcd_logo_plot(int x, int y) {} 385 #endif /* CONFIG_LCD_LOGO */ 386 387 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN) 388 #ifdef CONFIG_SPLASH_SCREEN_ALIGN 389 #define BMP_ALIGN_CENTER 0x7FFF 390 391 static void splash_align_axis(int *axis, unsigned long panel_size, 392 unsigned long picture_size) 393 { 394 unsigned long panel_picture_delta = panel_size - picture_size; 395 unsigned long axis_alignment; 396 397 if (*axis == BMP_ALIGN_CENTER) 398 axis_alignment = panel_picture_delta / 2; 399 else if (*axis < 0) 400 axis_alignment = panel_picture_delta + *axis + 1; 401 else 402 return; 403 404 *axis = max(0, (int)axis_alignment); 405 } 406 #endif 407 408 #ifdef CONFIG_LCD_BMP_RLE8 409 #define BMP_RLE8_ESCAPE 0 410 #define BMP_RLE8_EOL 0 411 #define BMP_RLE8_EOBMP 1 412 #define BMP_RLE8_DELTA 2 413 414 static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap, 415 int cnt) 416 { 417 while (cnt > 0) { 418 *(*fbp)++ = cmap[*bmap++]; 419 cnt--; 420 } 421 } 422 423 static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt) 424 { 425 ushort *fb = *fbp; 426 int cnt_8copy = cnt >> 3; 427 428 cnt -= cnt_8copy << 3; 429 while (cnt_8copy > 0) { 430 *fb++ = c; 431 *fb++ = c; 432 *fb++ = c; 433 *fb++ = c; 434 *fb++ = c; 435 *fb++ = c; 436 *fb++ = c; 437 *fb++ = c; 438 cnt_8copy--; 439 } 440 while (cnt > 0) { 441 *fb++ = c; 442 cnt--; 443 } 444 *fbp = fb; 445 } 446 447 /* 448 * Do not call this function directly, must be called from lcd_display_bitmap. 449 */ 450 static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb, 451 int x_off, int y_off) 452 { 453 uchar *bmap; 454 ulong width, height; 455 ulong cnt, runlen; 456 int x, y; 457 int decode = 1; 458 459 width = get_unaligned_le32(&bmp->header.width); 460 height = get_unaligned_le32(&bmp->header.height); 461 bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset); 462 463 x = 0; 464 y = height - 1; 465 466 while (decode) { 467 if (bmap[0] == BMP_RLE8_ESCAPE) { 468 switch (bmap[1]) { 469 case BMP_RLE8_EOL: 470 /* end of line */ 471 bmap += 2; 472 x = 0; 473 y--; 474 /* 16bpix, 2-byte per pixel, width should *2 */ 475 fb -= (width * 2 + lcd_line_length); 476 break; 477 case BMP_RLE8_EOBMP: 478 /* end of bitmap */ 479 decode = 0; 480 break; 481 case BMP_RLE8_DELTA: 482 /* delta run */ 483 x += bmap[2]; 484 y -= bmap[3]; 485 /* 16bpix, 2-byte per pixel, x should *2 */ 486 fb = (uchar *) (lcd_base + (y + y_off - 1) 487 * lcd_line_length + (x + x_off) * 2); 488 bmap += 4; 489 break; 490 default: 491 /* unencoded run */ 492 runlen = bmap[1]; 493 bmap += 2; 494 if (y < height) { 495 if (x < width) { 496 if (x + runlen > width) 497 cnt = width - x; 498 else 499 cnt = runlen; 500 draw_unencoded_bitmap( 501 (ushort **)&fb, 502 bmap, cmap, cnt); 503 } 504 x += runlen; 505 } 506 bmap += runlen; 507 if (runlen & 1) 508 bmap++; 509 } 510 } else { 511 /* encoded run */ 512 if (y < height) { 513 runlen = bmap[0]; 514 if (x < width) { 515 /* aggregate the same code */ 516 while (bmap[0] == 0xff && 517 bmap[2] != BMP_RLE8_ESCAPE && 518 bmap[1] == bmap[3]) { 519 runlen += bmap[2]; 520 bmap += 2; 521 } 522 if (x + runlen > width) 523 cnt = width - x; 524 else 525 cnt = runlen; 526 draw_encoded_bitmap((ushort **)&fb, 527 cmap[bmap[1]], cnt); 528 } 529 x += runlen; 530 } 531 bmap += 2; 532 } 533 } 534 } 535 #endif 536 537 __weak void fb_put_byte(uchar **fb, uchar **from) 538 { 539 *(*fb)++ = *(*from)++; 540 } 541 542 #if defined(CONFIG_BMP_16BPP) 543 __weak void fb_put_word(uchar **fb, uchar **from) 544 { 545 *(*fb)++ = *(*from)++; 546 *(*fb)++ = *(*from)++; 547 } 548 #endif /* CONFIG_BMP_16BPP */ 549 550 __weak void lcd_set_cmap(bmp_image_t *bmp, unsigned colors) 551 { 552 int i; 553 bmp_color_table_entry_t cte; 554 ushort *cmap = configuration_get_cmap(); 555 556 for (i = 0; i < colors; ++i) { 557 cte = bmp->color_table[i]; 558 *cmap = (((cte.red) << 8) & 0xf800) | 559 (((cte.green) << 3) & 0x07e0) | 560 (((cte.blue) >> 3) & 0x001f); 561 #if defined(CONFIG_MPC823) 562 cmap--; 563 #else 564 cmap++; 565 #endif 566 } 567 } 568 569 int lcd_display_bitmap(ulong bmp_image, int x, int y) 570 { 571 ushort *cmap_base = NULL; 572 ushort i, j; 573 uchar *fb; 574 bmp_image_t *bmp = (bmp_image_t *)map_sysmem(bmp_image, 0); 575 uchar *bmap; 576 ushort padded_width; 577 unsigned long width, height, byte_width; 578 unsigned long pwidth = panel_info.vl_col; 579 unsigned colors, bpix, bmp_bpix; 580 581 if (!bmp || !(bmp->header.signature[0] == 'B' && 582 bmp->header.signature[1] == 'M')) { 583 printf("Error: no valid bmp image at %lx\n", bmp_image); 584 585 return 1; 586 } 587 588 width = get_unaligned_le32(&bmp->header.width); 589 height = get_unaligned_le32(&bmp->header.height); 590 bmp_bpix = get_unaligned_le16(&bmp->header.bit_count); 591 592 colors = 1 << bmp_bpix; 593 594 bpix = NBITS(panel_info.vl_bpix); 595 596 if (bpix != 1 && bpix != 8 && bpix != 16 && bpix != 32) { 597 printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", 598 bpix, bmp_bpix); 599 600 return 1; 601 } 602 603 /* 604 * We support displaying 8bpp BMPs on 16bpp LCDs 605 * and displaying 24bpp BMPs on 32bpp LCDs 606 * */ 607 if (bpix != bmp_bpix && 608 !(bmp_bpix == 8 && bpix == 16) && 609 !(bmp_bpix == 24 && bpix == 32)) { 610 printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", 611 bpix, get_unaligned_le16(&bmp->header.bit_count)); 612 return 1; 613 } 614 615 debug("Display-bmp: %d x %d with %d colors\n", 616 (int)width, (int)height, (int)colors); 617 618 if (bmp_bpix == 8) 619 lcd_set_cmap(bmp, colors); 620 621 padded_width = (width & 0x3 ? (width & ~0x3) + 4 : width); 622 623 #ifdef CONFIG_SPLASH_SCREEN_ALIGN 624 splash_align_axis(&x, pwidth, width); 625 splash_align_axis(&y, panel_info.vl_row, height); 626 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */ 627 628 if ((x + width) > pwidth) 629 width = pwidth - x; 630 if ((y + height) > panel_info.vl_row) 631 height = panel_info.vl_row - y; 632 633 bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset); 634 fb = (uchar *)(lcd_base + 635 (y + height - 1) * lcd_line_length + x * bpix / 8); 636 637 switch (bmp_bpix) { 638 case 1: 639 case 8: { 640 cmap_base = configuration_get_cmap(); 641 #ifdef CONFIG_LCD_BMP_RLE8 642 u32 compression = get_unaligned_le32(&bmp->header.compression); 643 if (compression == BMP_BI_RLE8) { 644 if (bpix != 16) { 645 /* TODO implement render code for bpix != 16 */ 646 printf("Error: only support 16 bpix"); 647 return 1; 648 } 649 lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y); 650 break; 651 } 652 #endif 653 654 if (bpix != 16) 655 byte_width = width; 656 else 657 byte_width = width * 2; 658 659 for (i = 0; i < height; ++i) { 660 WATCHDOG_RESET(); 661 for (j = 0; j < width; j++) { 662 if (bpix != 16) { 663 fb_put_byte(&fb, &bmap); 664 } else { 665 *(uint16_t *)fb = cmap_base[*(bmap++)]; 666 fb += sizeof(uint16_t) / sizeof(*fb); 667 } 668 } 669 bmap += (padded_width - width); 670 fb -= byte_width + lcd_line_length; 671 } 672 break; 673 } 674 #if defined(CONFIG_BMP_16BPP) 675 case 16: 676 for (i = 0; i < height; ++i) { 677 WATCHDOG_RESET(); 678 for (j = 0; j < width; j++) 679 fb_put_word(&fb, &bmap); 680 681 bmap += (padded_width - width) * 2; 682 fb -= width * 2 + lcd_line_length; 683 } 684 break; 685 #endif /* CONFIG_BMP_16BPP */ 686 #if defined(CONFIG_BMP_24BMP) 687 case 24: 688 for (i = 0; i < height; ++i) { 689 for (j = 0; j < width; j++) { 690 *(fb++) = *(bmap++); 691 *(fb++) = *(bmap++); 692 *(fb++) = *(bmap++); 693 *(fb++) = 0; 694 } 695 fb -= lcd_line_length + width * (bpix / 8); 696 } 697 break; 698 #endif /* CONFIG_BMP_24BMP */ 699 #if defined(CONFIG_BMP_32BPP) 700 case 32: 701 for (i = 0; i < height; ++i) { 702 for (j = 0; j < width; j++) { 703 *(fb++) = *(bmap++); 704 *(fb++) = *(bmap++); 705 *(fb++) = *(bmap++); 706 *(fb++) = *(bmap++); 707 } 708 fb -= lcd_line_length + width * (bpix / 8); 709 } 710 break; 711 #endif /* CONFIG_BMP_32BPP */ 712 default: 713 break; 714 }; 715 716 lcd_sync(); 717 return 0; 718 } 719 #endif 720 721 static void lcd_logo(void) 722 { 723 lcd_logo_plot(0, 0); 724 725 #ifdef CONFIG_LCD_INFO 726 lcd_set_col(LCD_INFO_X / VIDEO_FONT_WIDTH); 727 lcd_set_row(LCD_INFO_Y / VIDEO_FONT_HEIGHT); 728 lcd_show_board_info(); 729 #endif /* CONFIG_LCD_INFO */ 730 } 731 732 #ifdef CONFIG_SPLASHIMAGE_GUARD 733 static int on_splashimage(const char *name, const char *value, enum env_op op, 734 int flags) 735 { 736 ulong addr; 737 int aligned; 738 739 if (op == env_op_delete) 740 return 0; 741 742 addr = simple_strtoul(value, NULL, 16); 743 /* See README.displaying-bmps */ 744 aligned = (addr % 4 == 2); 745 if (!aligned) { 746 printf("Invalid splashimage value. Value must be 16 bit aligned, but not 32 bit aligned\n"); 747 return -1; 748 } 749 750 return 0; 751 } 752 753 U_BOOT_ENV_CALLBACK(splashimage, on_splashimage); 754 #endif 755 756 int lcd_get_pixel_width(void) 757 { 758 return panel_info.vl_col; 759 } 760 761 int lcd_get_pixel_height(void) 762 { 763 return panel_info.vl_row; 764 } 765