X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fvideo%2Fcfb_console.c;h=dd849c2dc13207bae02c8a6479bfabe8085fe8f6;hb=b5d58d8500bfb918c7fec56f241e6ee1078c2be0;hp=49f0a2e04051b1696ca79f0068666e61145b3318;hpb=45e565337a90bbca0c1bb712b5e008b7c0b18bd5;p=u-boot diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 49f0a2e040..dd849c2dc1 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -230,8 +230,8 @@ CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability of the #error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined #endif void console_cursor (int state); -#define CURSOR_ON console_cursor(1); -#define CURSOR_OFF console_cursor(0); +#define CURSOR_ON console_cursor(1) +#define CURSOR_OFF console_cursor(0) #define CURSOR_SET #ifndef CONFIG_I8042_KBD #warning Cursor drawing on/off needs timer function s.a. drivers/input/i8042.c @@ -248,8 +248,8 @@ void console_cursor (int state); #endif #define CURSOR_ON #define CURSOR_OFF video_putchar(console_col * VIDEO_FONT_WIDTH,\ - console_row * VIDEO_FONT_HEIGHT, ' '); -#define CURSOR_SET video_set_cursor(); + console_row * VIDEO_FONT_HEIGHT, ' ') +#define CURSOR_SET video_set_cursor() #endif /* CONFIG_VIDEO_SW_CURSOR */ @@ -260,7 +260,7 @@ void console_cursor (int state); #define CURSOR_ON #define CURSOR_OFF #define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \ - (console_row * VIDEO_FONT_HEIGHT) + video_logo_height); + (console_row * VIDEO_FONT_HEIGHT) + video_logo_height) #endif /* CONFIG_VIDEO_HW_CURSOR */ #ifdef CONFIG_VIDEO_LOGO @@ -651,7 +651,8 @@ static void console_scrollup (void) static void console_back (void) { - CURSOR_OFF console_col--; + CURSOR_OFF; + console_col--; if (console_col < 0) { console_col = CONSOLE_COLS - 1; @@ -674,7 +675,7 @@ static void console_newline (void) is >= CONSOLE_COLS */ if (console_col < CONSOLE_COLS) - CURSOR_OFF + CURSOR_OFF; console_row++; console_col = 0; @@ -690,7 +691,8 @@ static void console_newline (void) static void console_cr (void) { - CURSOR_OFF console_col = 0; + CURSOR_OFF; + console_col = 0; } /*****************************************************************************/ @@ -711,7 +713,8 @@ void video_putc (const char c) break; case 9: /* tab 8 */ - CURSOR_OFF console_col |= 0x0008; + CURSOR_OFF; + console_col |= 0x0008; console_col &= ~0x0007; if (console_col >= CONSOLE_COLS) @@ -734,7 +737,8 @@ void video_putc (const char c) nl = 0; } } -CURSOR_SET} + CURSOR_SET; +} /*****************************************************************************/ @@ -749,6 +753,18 @@ void video_puts (const char *s) /*****************************************************************************/ +/* + * Do not enforce drivers (or board code) to provide empty + * video_set_lut() if they do not support 8 bpp format. + * Implement weak default function instead. + */ +void __video_set_lut (unsigned int index, unsigned char r, + unsigned char g, unsigned char b) +{ +} +void video_set_lut (unsigned int, unsigned char, unsigned char, unsigned char) + __attribute__((weak, alias("__video_set_lut"))); + #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN) #define FILL_8BIT_332RGB(r,g,b) { \ @@ -802,9 +818,194 @@ static void inline fill_555rgb_pswap(uchar *fb, int x, } #endif +/* + * RLE8 bitmap support + */ + +#ifdef CONFIG_VIDEO_BMP_RLE8 +/* Pre-calculated color table entry */ +struct palette { + union { + unsigned short w; /* word */ + unsigned int dw; /* double word */ + } ce; /* color entry */ +}; + +/* + * Helper to draw encoded/unencoded run. + */ +static void draw_bitmap (uchar **fb, uchar *bm, struct palette *p, + int cnt, int enc) +{ + ulong addr = (ulong)*fb; + int *off; + int enc_off = 1; + int i; + + /* + * Setup offset of the color index in the bitmap. + * Color index of encoded run is at offset 1. + */ + off = enc ? &enc_off : &i; + + switch (VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + for (i = 0; i < cnt; i++) + *(unsigned char *)addr++ = bm[*off]; + break; + case GDF_15BIT_555RGB: + case GDF_16BIT_565RGB: + /* differences handled while pre-calculating palette */ + for (i = 0; i < cnt; i++) { + *(unsigned short *)addr = p[bm[*off]].ce.w; + addr += 2; + } + break; + case GDF_32BIT_X888RGB: + for (i = 0; i < cnt; i++) { + *(unsigned long *)addr = p[bm[*off]].ce.dw; + addr += 4; + } + break; + } + *fb = (uchar *)addr; /* return modified address */ +} + +static int display_rle8_bitmap (bmp_image_t *img, int xoff, int yoff, + int width, int height) +{ + unsigned char *bm; + unsigned char *fbp; + unsigned int cnt, runlen; + int decode = 1; + int x, y, bpp, i, ncolors; + struct palette p[256]; + bmp_color_table_entry_t cte; + int green_shift, red_off; + + x = 0; + y = __le32_to_cpu(img->header.height) - 1; + ncolors = __le32_to_cpu(img->header.colors_used); + bpp = VIDEO_PIXEL_SIZE; + fbp = (unsigned char *)((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + xoff) * bpp); + + bm = (uchar *)img + __le32_to_cpu(img->header.data_offset); + + /* pre-calculate and setup palette */ + switch (VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + video_set_lut (i, cte.red, cte.green, cte.blue); + } + break; + case GDF_15BIT_555RGB: + case GDF_16BIT_565RGB: + if (VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) { + green_shift = 3; + red_off = 10; + } else { + green_shift = 2; + red_off = 11; + } + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + p[i].ce.w = SWAP16((unsigned short) + (((cte.red >> 3) << red_off) | + ((cte.green >> green_shift) << 5) | + cte.blue >> 3)); + } + break; + case GDF_32BIT_X888RGB: + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + p[i].ce.dw = SWAP32((cte.red << 16) | (cte.green << 8) | + cte.blue); + } + break; + default: + printf("RLE Bitmap unsupported in video mode 0x%x\n", + VIDEO_DATA_FORMAT); + return -1; + } + + while (decode) { + switch (bm[0]) { + case 0: + switch (bm[1]) { + case 0: + /* scan line end marker */ + bm += 2; + x = 0; + y--; + fbp = (unsigned char *) + ((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + + xoff) * bpp); + continue; + case 1: + /* end of bitmap data marker */ + decode = 0; + break; + case 2: + /* run offset marker */ + x += bm[2]; + y -= bm[3]; + fbp = (unsigned char *) + ((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + + x + xoff) * bpp); + bm += 4; + break; + default: + /* unencoded run */ + cnt = bm[1]; + runlen = cnt; + bm += 2; + if (y < height) { + if (x >= width) { + x += runlen; + goto next_run; + } + if (x + runlen > width) + cnt = width - x; + + draw_bitmap (&fbp, bm, p, cnt, 0); + x += runlen; + } +next_run: + bm += runlen; + if (runlen & 1) + bm++; /* 0 padding if length is odd */ + } + break; + default: + /* encoded run */ + if (y < height) { /* only draw into visible area */ + cnt = bm[0]; + runlen = cnt; + if (x >= width) { + x += runlen; + bm += 2; + continue; + } + if (x + runlen > width) + cnt = width - x; + + draw_bitmap (&fbp, bm, p, cnt, 1); + x += runlen; + } + bm += 2; + break; + } + } + return 0; +} +#endif + /* * Display the BMP file located at address bmp_image. - * Only uncompressed */ int video_display_bitmap (ulong bmp_image, int x, int y) { @@ -872,7 +1073,11 @@ int video_display_bitmap (ulong bmp_image, int x, int y) debug ("Display-bmp: %d x %d with %d colors\n", width, height, colors); - if (compression != BMP_BI_RGB) { + if (compression != BMP_BI_RGB +#ifdef CONFIG_VIDEO_BMP_RLE8 + && compression != BMP_BI_RLE8 +#endif + ) { printf ("Error: compression type %ld not supported\n", compression); #ifdef CONFIG_VIDEO_BMP_GZIP @@ -906,12 +1111,55 @@ int video_display_bitmap (ulong bmp_image, int x, int y) ((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) + x * VIDEO_PIXEL_SIZE); - /* We handle only 8bpp or 24 bpp bitmap */ +#ifdef CONFIG_VIDEO_BMP_RLE8 + if (compression == BMP_BI_RLE8) { + return display_rle8_bitmap(bmp, + x, y, width, height); + } +#endif + + /* We handle only 4, 8, or 24 bpp bitmaps */ switch (le16_to_cpu (bmp->header.bit_count)) { + case 4: + padded_line -= width / 2; + ycount = height; + + switch (VIDEO_DATA_FORMAT) { + case GDF_32BIT_X888RGB: + while (ycount--) { + WATCHDOG_RESET (); + /* + * Don't assume that 'width' is an + * even number + */ + for (xcount = 0; xcount < width; xcount++) { + uchar idx; + + if (xcount & 1) { + idx = *bmap & 0xF; + bmap++; + } else + idx = *bmap >> 4; + cte = bmp->color_table[idx]; + FILL_32BIT_X888RGB(cte.red, cte.green, + cte.blue); + } + bmap += padded_line; + fb -= (VIDEO_VISIBLE_COLS + width) * + VIDEO_PIXEL_SIZE; + } + break; + default: + puts("4bpp bitmap unsupported with current " + "video mode\n"); + break; + } + break; + case 8: padded_line -= width; if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) { - /* Copy colormap */ + /* Copy colormap */ for (xcount = 0; xcount < colors; ++xcount) { cte = bmp->color_table[xcount]; video_set_lut (xcount, cte.red, cte.green, cte.blue); @@ -1113,11 +1361,11 @@ void logo_plot (void *screen, int width, int x, int y) #ifdef CONFIG_VIDEO_BMP_LOGO source = bmp_logo_bitmap; - /* Allocate temporary space for computing colormap */ + /* Allocate temporary space for computing colormap */ logo_red = malloc (BMP_LOGO_COLORS); logo_green = malloc (BMP_LOGO_COLORS); logo_blue = malloc (BMP_LOGO_COLORS); - /* Compute color map */ + /* Compute color map */ for (i = 0; i < VIDEO_LOGO_COLORS; i++) { logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4; logo_green[i] = (bmp_logo_palette[i] & 0x00f0);