]> git.sur5r.net Git - u-boot/blobdiff - drivers/video/cfb_console.c
Merge branch 'next' of /home/wd/git/u-boot/next
[u-boot] / drivers / video / cfb_console.c
index 49f0a2e04051b1696ca79f0068666e61145b3318..dd849c2dc13207bae02c8a6479bfabe8085fe8f6 100644 (file)
@@ -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);