]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/video/cfb_console.c
Merge branch 'master' of git://git.denx.de/u-boot-mpc83xx
[people/ms/u-boot.git] / drivers / video / cfb_console.c
index 5ee2314f3cd5e83c05bb8c3c53cedb08a8018c7b..d1f47c9157130a20678199d72e30a4c1c57c3004 100644 (file)
@@ -146,9 +146,11 @@ CONFIG_VIDEO_HW_CURSOR:         - Uses the hardware cursor capability of the
 #ifdef CONFIG_VIDEO_CORALP
 #define VIDEO_FB_LITTLE_ENDIAN
 #endif
+#ifdef CONFIG_VIDEO_MB862xx_ACCEL
 #define VIDEO_HW_RECTFILL
 #define VIDEO_HW_BITBLT
 #endif
+#endif
 
 /*****************************************************************************/
 /* Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc            */
@@ -183,7 +185,7 @@ CONFIG_VIDEO_HW_CURSOR:          - Uses the hardware cursor capability of the
 
 #include <version.h>
 #include <linux/types.h>
-#include <devices.h>
+#include <stdio_dev.h>
 #include <video_font.h>
 
 #if defined(CONFIG_CMD_DATE)
@@ -193,6 +195,11 @@ CONFIG_VIDEO_HW_CURSOR:         - Uses the hardware cursor capability of the
 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
 #include <watchdog.h>
 #include <bmp_layout.h>
+
+#ifdef CONFIG_SPLASH_SCREEN_ALIGN
+#define BMP_ALIGN_CENTER       0x7FFF
+#endif
+
 #endif
 
 /*****************************************************************************/
@@ -253,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
@@ -291,7 +298,7 @@ void        console_cursor (int state);
 #define VIDEO_BURST_LEN                (VIDEO_COLS/8)
 
 #ifdef CONFIG_VIDEO_LOGO
-#define CONSOLE_ROWS           ((VIDEO_ROWS - VIDEO_LOGO_HEIGHT) / VIDEO_FONT_HEIGHT)
+#define CONSOLE_ROWS           ((VIDEO_ROWS - video_logo_height) / VIDEO_FONT_HEIGHT)
 #else
 #define CONSOLE_ROWS           (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
 #endif
@@ -314,7 +321,7 @@ void        console_cursor (int state);
 #else
 #define SWAP16(x)       (x)
 #define SWAP32(x)       (x)
-#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
+#if defined(VIDEO_FB_16BPP_WORD_SWAP)
 #define SHORTSWAP32(x)  ( ((x) >> 16) | ((x) << 16) )
 #else
 #define SHORTSWAP32(x)  (x)
@@ -342,6 +349,8 @@ static GraphicDevice *pGD;  /* Pointer to Graphic array */
 static void *video_fb_address;         /* frame buffer address */
 static void *video_console_address;    /* console buffer start address */
 
+static int video_logo_height = VIDEO_LOGO_HEIGHT;
+
 static int console_col = 0; /* cursor col */
 static int console_row = 0; /* cursor row */
 
@@ -396,8 +405,6 @@ static const int video_font_draw_table32[16][4] = {
            { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } };
 
 
-int gunzip(void *, int, unsigned char *, unsigned long *);
-
 /******************************************************************************/
 
 static void video_drawchars (int xx, int yy, unsigned char *s, int count)
@@ -522,7 +529,7 @@ static inline void video_drawstring (int xx, int yy, unsigned char *s)
 
 static void video_putchar (int xx, int yy, unsigned char c)
 {
-       video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, &c, 1);
+       video_drawchars (xx, yy + video_logo_height, &c, 1);
 }
 
 /*****************************************************************************/
@@ -615,11 +622,11 @@ static void console_scrollup (void)
 #ifdef VIDEO_HW_BITBLT
        video_hw_bitblt (VIDEO_PIXEL_SIZE,      /* bytes per pixel */
                         0,     /* source pos x */
-                        VIDEO_LOGO_HEIGHT + VIDEO_FONT_HEIGHT, /* source pos y */
+                        video_logo_height + VIDEO_FONT_HEIGHT, /* source pos y */
                         0,     /* dest pos x */
-                        VIDEO_LOGO_HEIGHT,     /* dest pos y */
+                        video_logo_height,     /* dest pos y */
                         VIDEO_VISIBLE_COLS,    /* frame width */
-                        VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT     /* frame height */
+                        VIDEO_VISIBLE_ROWS - video_logo_height - VIDEO_FONT_HEIGHT     /* frame height */
                );
 #else
        memcpyl (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
@@ -795,9 +802,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)
 {
@@ -865,7 +1057,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
@@ -877,6 +1073,18 @@ int video_display_bitmap (ulong bmp_image, int x, int y)
 
        padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
 
+#ifdef CONFIG_SPLASH_SCREEN_ALIGN
+       if (x == BMP_ALIGN_CENTER)
+               x = max(0, (VIDEO_VISIBLE_COLS - width) / 2);
+       else if (x < 0)
+               x = max(0, VIDEO_VISIBLE_COLS - width + x + 1);
+
+       if (y == BMP_ALIGN_CENTER)
+               y = max(0, (VIDEO_VISIBLE_ROWS - height) / 2);
+       else if (y < 0)
+               y = max(0, VIDEO_VISIBLE_ROWS - height + y + 1);
+#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
+
        if ((x + width) > VIDEO_VISIBLE_COLS)
                width = VIDEO_VISIBLE_COLS - x;
        if ((y + height) > VIDEO_VISIBLE_ROWS)
@@ -887,6 +1095,13 @@ int video_display_bitmap (ulong bmp_image, int x, int y)
                        ((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) +
                        x * VIDEO_PIXEL_SIZE);
 
+#ifdef CONFIG_VIDEO_BMP_RLE8
+       if (compression == BMP_BI_RLE8) {
+               return display_rle8_bitmap(bmp,
+                                          x, y, width, height);
+       }
+#endif
+
        /* We handle only 8bpp or 24 bpp bitmap */
        switch (le16_to_cpu (bmp->header.bit_count)) {
        case 8:
@@ -1084,7 +1299,7 @@ void logo_plot (void *screen, int width, int x, int y)
 
        int xcount, i;
        int skip   = (width - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
-       int ycount = VIDEO_LOGO_HEIGHT;
+       int ycount = video_logo_height;
        unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
        unsigned char *source;
        unsigned char *dest = (unsigned char *)screen +
@@ -1188,9 +1403,27 @@ static void *video_logo (void)
        ulong addr;
 
        if ((s = getenv ("splashimage")) != NULL) {
+               int x = 0, y = 0;
+
                addr = simple_strtoul (s, NULL, 16);
+#ifdef CONFIG_SPLASH_SCREEN_ALIGN
+               if ((s = getenv ("splashpos")) != NULL) {
+                       if (s[0] == 'm')
+                               x = BMP_ALIGN_CENTER;
+                       else
+                               x = simple_strtol (s, NULL, 0);
+
+                       if ((s = strchr (s + 1, ',')) != NULL) {
+                               if (s[1] == 'm')
+                                       y = BMP_ALIGN_CENTER;
+                               else
+                                       y = simple_strtol (s + 1, NULL, 0);
+                       }
+               }
+#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
 
-               if (video_display_bitmap (addr, 0, 0) == 0) {
+               if (video_display_bitmap (addr, x, y) == 0) {
+                       video_logo_height = 0;
                        return ((void *) (video_fb_address));
                }
        }
@@ -1215,7 +1448,7 @@ static void *video_logo (void)
 
 #ifdef CONFIG_CONSOLE_EXTRA_INFO
        {
-               int i, n = ((VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
+               int i, n = ((video_logo_height - VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
 
                for (i = 1; i < n; i++) {
                        video_get_info_str (i, info);
@@ -1244,7 +1477,7 @@ static void *video_logo (void)
        }
 #endif
 
-       return (video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN);
+       return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
 }
 #endif
 
@@ -1330,53 +1563,57 @@ static int video_init (void)
 
 /*****************************************************************************/
 
+/*
+ * Implement a weak default function for boards that optionally
+ * need to skip the video initialization.
+ */
+int __board_video_skip(void)
+{
+       /* As default, don't skip test */
+       return 0;
+}
+int board_video_skip(void) __attribute__((weak, alias("__board_video_skip")));
+
 int drv_video_init (void)
 {
        int skip_dev_init;
-       device_t console_dev;
+       struct stdio_dev console_dev;
 
-       skip_dev_init = 0;
+       /* Check if video initialization should be skipped */
+       if (board_video_skip())
+               return 0;
 
        /* Init video chip - returns with framebuffer cleared */
-       if (video_init () == -1)
-               skip_dev_init = 1;
+       skip_dev_init = (video_init () == -1);
 
-#ifdef CONFIG_VGA_AS_SINGLE_DEVICE
-       /* Devices VGA and Keyboard will be assigned seperately */
-       /* Init vga device */
-       if (!skip_dev_init) {
-               memset (&console_dev, 0, sizeof (console_dev));
-               strcpy (console_dev.name, "vga");
-               console_dev.ext = DEV_EXT_VIDEO;        /* Video extensions */
-               console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
-               console_dev.putc = video_putc;  /* 'putc' function */
-               console_dev.puts = video_puts;  /* 'puts' function */
-               console_dev.tstc = NULL;        /* 'tstc' function */
-               console_dev.getc = NULL;        /* 'getc' function */
-
-               if (device_register (&console_dev) == 0)
-                       return 1;
-       }
-#else
+#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
        PRINTD ("KBD: Keyboard init ...\n");
-       if (VIDEO_KBD_INIT_FCT == -1)
-               skip_dev_init = 1;
-
-       /* Init console device */
-       if (!skip_dev_init) {
-               memset (&console_dev, 0, sizeof (console_dev));
-               strcpy (console_dev.name, "vga");
-               console_dev.ext = DEV_EXT_VIDEO;        /* Video extensions */
-               console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
-               console_dev.putc = video_putc;  /* 'putc' function */
-               console_dev.puts = video_puts;  /* 'puts' function */
-               console_dev.tstc = VIDEO_TSTC_FCT;      /* 'tstc' function */
-               console_dev.getc = VIDEO_GETC_FCT;      /* 'getc' function */
-
-               if (device_register (&console_dev) == 0)
-                       return 1;
-       }
+       skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1);
+#endif
+
+       if (skip_dev_init)
+               return 0;
+
+       /* Init vga device */
+       memset (&console_dev, 0, sizeof (console_dev));
+       strcpy (console_dev.name, "vga");
+       console_dev.ext = DEV_EXT_VIDEO;        /* Video extensions */
+       console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+       console_dev.putc = video_putc;  /* 'putc' function */
+       console_dev.puts = video_puts;  /* 'puts' function */
+       console_dev.tstc = NULL;        /* 'tstc' function */
+       console_dev.getc = NULL;        /* 'getc' function */
+
+#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
+       /* Also init console device */
+       console_dev.flags |= DEV_FLAGS_INPUT;
+       console_dev.tstc = VIDEO_TSTC_FCT;      /* 'tstc' function */
+       console_dev.getc = VIDEO_GETC_FCT;      /* 'getc' function */
 #endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
-       /* No console dev available */
-       return 0;
+
+       if (stdio_register (&console_dev) != 0)
+               return 0;
+
+       /* Return success */
+       return 1;
 }