]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - drivers/video/cfb_console.c
video: cfb_console: flush dcache for frame buffer in DRAM
[karo-tx-uboot.git] / drivers / video / cfb_console.c
index 917bba6398507528ffcac2f9212bde055207b5d8..92fa77d27f725b9bea8070ae5bed223907553c89 100644 (file)
 #include <common.h>
 #include <version.h>
 #include <malloc.h>
+#include <linux/compiler.h>
 
 /*
  * Console device defines with SMI graphic
 #endif
 #endif
 
+/*
+ * Defines for the i.MX31 driver (mx3fb.c)
+ */
+#if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_MX5)
+#define VIDEO_FB_16BPP_WORD_SWAP
+#endif
+
 /*
  * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc.
  */
 #include <linux/types.h>
 #include <stdio_dev.h>
 #include <video_font.h>
+#include <video_font_data.h>
 
 #if defined(CONFIG_CMD_DATE)
 #include <rtc.h>
 #define CURSOR_SET
 #endif
 
-#ifdef CONFIG_CONSOLE_CURSOR
-#ifdef CURSOR_ON
+#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
+#if defined(CURSOR_ON) || \
+       (defined(CONFIG_CONSOLE_CURSOR) && defined(CONFIG_VIDEO_SW_CURSOR))
 #error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
        or CONFIG_VIDEO_HW_CURSOR can be defined
 #endif
@@ -242,27 +252,18 @@ void console_cursor(int state);
 
 #define CURSOR_ON  console_cursor(1)
 #define CURSOR_OFF console_cursor(0)
-#define CURSOR_SET
+#define CURSOR_SET video_set_cursor()
+#endif /* CONFIG_CONSOLE_CURSOR || CONFIG_VIDEO_SW_CURSOR */
+
+#ifdef CONFIG_CONSOLE_CURSOR
+#ifndef        CONFIG_CONSOLE_TIME
+#error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
+#endif
 #ifndef CONFIG_I8042_KBD
 #warning Cursor drawing on/off needs timer function s.a. drivers/input/i8042.c
 #endif
-#else
-#ifdef CONFIG_CONSOLE_TIME
-#error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
-#endif
 #endif /* CONFIG_CONSOLE_CURSOR */
 
-#ifdef CONFIG_VIDEO_SW_CURSOR
-#ifdef CURSOR_ON
-#error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
-       or CONFIG_VIDEO_HW_CURSOR can be defined
-#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()
-#endif /* CONFIG_VIDEO_SW_CURSOR */
-
 
 #ifdef CONFIG_VIDEO_HW_CURSOR
 #ifdef CURSOR_ON
@@ -278,6 +279,7 @@ void console_cursor(int state);
 #ifdef CONFIG_VIDEO_LOGO
 #ifdef CONFIG_VIDEO_BMP_LOGO
 #include <bmp_logo.h>
+#include <bmp_logo_data.h>
 #define VIDEO_LOGO_WIDTH       BMP_LOGO_WIDTH
 #define VIDEO_LOGO_HEIGHT      BMP_LOGO_HEIGHT
 #define VIDEO_LOGO_LUT_OFFSET  BMP_LOGO_OFFSET
@@ -348,13 +350,6 @@ void console_cursor(int state);
 #endif
 #endif
 
-#if defined(DEBUG) || defined(DEBUG_CFB_CONSOLE)
-#define PRINTD(x)              printf(x)
-#else
-#define PRINTD(x)
-#endif
-
-
 #ifdef CONFIG_CONSOLE_EXTRA_INFO
 /*
  * setup a board string: type, speed, etc.
@@ -365,6 +360,8 @@ void console_cursor(int state);
 extern void video_get_info_str(int line_number,        char *info);
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Locals */
 static GraphicDevice *pGD;     /* Pointer to Graphic array */
 
@@ -373,11 +370,17 @@ 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 */
+static int __maybe_unused cursor_state;
+static int __maybe_unused old_col;
+static int __maybe_unused old_row;
+
+static int console_col;                /* cursor col */
+static int console_row;                /* cursor row */
 
 static u32 eorx, fgx, bgx;     /* color pats */
 
+static int cfb_do_flush_cache;
+
 static const int video_font_draw_table8[] = {
        0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
        0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
@@ -431,7 +434,6 @@ static const int video_font_draw_table32[16][4] = {
        {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}
 };
 
-
 static void video_drawchars(int xx, int yy, unsigned char *s, int count)
 {
        u8 *cdat, *dest, *dest0;
@@ -555,6 +557,8 @@ static void video_drawchars(int xx, int yy, unsigned char *s, int count)
                                        SWAP32((video_font_draw_table32
                                                [bits & 15][3] & eorx) ^ bgx);
                        }
+                       if (cfb_do_flush_cache)
+                               flush_cache((ulong)dest0, 32);
                        dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
                        s++;
                }
@@ -607,27 +611,30 @@ static void video_putchar(int xx, int yy, unsigned char c)
 #if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
 static void video_set_cursor(void)
 {
-       /* swap drawing colors */
-       eorx = fgx;
-       fgx = bgx;
-       bgx = eorx;
-       eorx = fgx ^ bgx;
-       /* draw cursor */
-       video_putchar(console_col * VIDEO_FONT_WIDTH,
-                     console_row * VIDEO_FONT_HEIGHT, ' ');
-       /* restore drawing colors */
-       eorx = fgx;
-       fgx = bgx;
-       bgx = eorx;
-       eorx = fgx ^ bgx;
+       if (cursor_state)
+               console_cursor(0);
+       console_cursor(1);
 }
-#endif
 
-#ifdef CONFIG_CONSOLE_CURSOR
-void console_cursor(int state)
+static void video_invertchar(int xx, int yy)
 {
-       static int last_state = 0;
+       int firstx = xx * VIDEO_PIXEL_SIZE;
+       int lastx = (xx + VIDEO_FONT_WIDTH) * VIDEO_PIXEL_SIZE;
+       int firsty = yy * VIDEO_LINE_LEN;
+       int lasty = (yy + VIDEO_FONT_HEIGHT) * VIDEO_LINE_LEN;
+       int x, y;
+       for (y = firsty; y < lasty; y += VIDEO_LINE_LEN) {
+               for (x = firstx; x < lastx; x++) {
+                       u8 *dest = (u8 *)(video_fb_address) + x + y;
+                       *dest = ~*dest;
+                       if (cfb_do_flush_cache)
+                               flush_cache((ulong)dest, 4);
+               }
+       }
+}
 
+void console_cursor(int state)
+{
 #ifdef CONFIG_CONSOLE_TIME
        struct rtc_time tm;
        char info[16];
@@ -649,17 +656,22 @@ void console_cursor(int state)
        }
 #endif
 
-       if (state && (last_state != state)) {
-               video_set_cursor();
-       }
-
-       if (!state && (last_state != state)) {
-               /* clear cursor */
-               video_putchar(console_col * VIDEO_FONT_WIDTH,
-                             console_row * VIDEO_FONT_HEIGHT, ' ');
+       if (cursor_state != state) {
+               if (cursor_state) {
+                       /* turn off the cursor */
+                       video_invertchar(old_col * VIDEO_FONT_WIDTH,
+                                        old_row * VIDEO_FONT_HEIGHT +
+                                        video_logo_height);
+               } else {
+                       /* turn off the cursor and record where it is */
+                       video_invertchar(console_col * VIDEO_FONT_WIDTH,
+                                        console_row * VIDEO_FONT_HEIGHT +
+                                        video_logo_height);
+                       old_col = console_col;
+                       old_row = console_row;
+               }
+               cursor_state = state;
        }
-
-       last_state = state;
 }
 #endif
 
@@ -679,6 +691,43 @@ static void memcpyl(int *d, int *s, int c)
 }
 #endif
 
+static void console_clear_line(int line, int begin, int end)
+{
+#ifdef VIDEO_HW_RECTFILL
+       video_hw_rectfill(VIDEO_PIXEL_SIZE,             /* bytes per pixel */
+                         VIDEO_FONT_WIDTH * begin,     /* dest pos x */
+                         video_logo_height +
+                         VIDEO_FONT_HEIGHT * line,     /* dest pos y */
+                         VIDEO_FONT_WIDTH * (end - begin + 1), /* fr. width */
+                         VIDEO_FONT_HEIGHT,            /* frame height */
+                         bgx                           /* fill color */
+               );
+#else
+       if (begin == 0 && (end + 1) == CONSOLE_COLS) {
+               memsetl(CONSOLE_ROW_FIRST +
+                       CONSOLE_ROW_SIZE * line,        /* offset of row */
+                       CONSOLE_ROW_SIZE >> 2,          /* length of row */
+                       bgx                             /* fill color */
+               );
+       } else {
+               void *offset;
+               int i, size;
+
+               offset = CONSOLE_ROW_FIRST +
+                        CONSOLE_ROW_SIZE * line +      /* offset of row */
+                        VIDEO_FONT_WIDTH *
+                        VIDEO_PIXEL_SIZE * begin;      /* offset of col */
+               size = VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE * (end - begin + 1);
+               size >>= 2; /* length to end for memsetl() */
+               /* fill at col offset of i'th line using bgx as fill color */
+               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+                       memsetl(offset + i * VIDEO_LINE_LEN, size, bgx);
+       }
+#endif
+       if (cfb_do_flush_cache)
+               flush_cache((ulong)CONSOLE_ROW_FIRST, CONSOLE_SIZE);
+}
+
 static void console_scrollup(void)
 {
        /* copy up rows ignoring the first one */
@@ -699,25 +748,12 @@ static void console_scrollup(void)
        memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
                CONSOLE_SCROLL_SIZE >> 2);
 #endif
-
        /* clear the last one */
-#ifdef VIDEO_HW_RECTFILL
-       video_hw_rectfill(VIDEO_PIXEL_SIZE,     /* bytes per pixel */
-                         0,                    /* dest pos x */
-                         VIDEO_VISIBLE_ROWS
-                         - VIDEO_FONT_HEIGHT,  /* dest pos y */
-                         VIDEO_VISIBLE_COLS,   /* frame width */
-                         VIDEO_FONT_HEIGHT,    /* frame height */
-                         CONSOLE_BG_COL        /* fill color */
-               );
-#else
-       memsetl(CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, CONSOLE_BG_COL);
-#endif
+       console_clear_line(CONSOLE_ROWS - 1, 0, CONSOLE_COLS - 1);
 }
 
 static void console_back(void)
 {
-       CURSOR_OFF;
        console_col--;
 
        if (console_col < 0) {
@@ -726,19 +762,10 @@ static void console_back(void)
                if (console_row < 0)
                        console_row = 0;
        }
-       video_putchar(console_col * VIDEO_FONT_WIDTH,
-                     console_row * VIDEO_FONT_HEIGHT, ' ');
 }
 
 static void console_newline(void)
 {
-       /* Check if last character in the line was just drawn. If so, cursor was
-          overwriten and need not to be cleared. Cursor clearing without this
-          check causes overwriting the 1st character of the line if line lenght
-          is >= CONSOLE_COLS
-        */
-       if (console_col < CONSOLE_COLS)
-               CURSOR_OFF;
        console_row++;
        console_col = 0;
 
@@ -754,7 +781,6 @@ static void console_newline(void)
 
 static void console_cr(void)
 {
-       CURSOR_OFF;
        console_col = 0;
 }
 
@@ -762,6 +788,8 @@ void video_putc(const char c)
 {
        static int nl = 1;
 
+       CURSOR_OFF;
+
        switch (c) {
        case 13:                /* back to first column */
                console_cr();
@@ -774,7 +802,6 @@ void video_putc(const char c)
                break;
 
        case 9:         /* tab 8 */
-               CURSOR_OFF;
                console_col |= 0x0008;
                console_col &= ~0x0007;
 
@@ -786,6 +813,9 @@ void video_putc(const char c)
                console_back();
                break;
 
+       case 7:         /* bell */
+               break;  /* ignored */
+
        default:                /* draw the char */
                video_putchar(console_col * VIDEO_FONT_WIDTH,
                              console_row * VIDEO_FONT_HEIGHT, c);
@@ -1152,7 +1182,7 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
        colors = le32_to_cpu(bmp->header.colors_used);
        compression = le32_to_cpu(bmp->header.compression);
 
-       debug("Display-bmp: %d x %d  with %d colors\n",
+       debug("Display-bmp: %ld x %ld  with %d colors\n",
              width, height, colors);
 
        if (compression != BMP_BI_RGB
@@ -1560,24 +1590,28 @@ void logo_plot(void *screen, int width, int x, int y)
 static void *video_logo(void)
 {
        char info[128];
-       int space, len, y_off = 0;
+       int space, len;
+       __maybe_unused int y_off = 0;
 
 #ifdef CONFIG_SPLASH_SCREEN
        char *s;
        ulong addr;
 
-       if ((s = getenv("splashimage")) != NULL) {
+       s = getenv("splashimage");
+       if (s != NULL) {
                int x = 0, y = 0;
 
                addr = simple_strtoul(s, NULL, 16);
 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
-               if ((s = getenv("splashpos")) != NULL) {
+               s = getenv("splashpos");
+               if (s != NULL) {
                        if (s[0] == 'm')
                                x = BMP_ALIGN_CENTER;
                        else
                                x = simple_strtol(s, NULL, 0);
 
-                       if ((s = strchr(s + 1, ',')) != NULL) {
+                       s = strchr(s + 1, ',');
+                       if (s != NULL) {
                                if (s[1] == 'm')
                                        y = BMP_ALIGN_CENTER;
                                else
@@ -1651,11 +1685,35 @@ static void *video_logo(void)
 }
 #endif
 
+static int cfb_fb_is_in_dram(void)
+{
+       bd_t *bd = gd->bd;
+#if defined(CONFIG_ARM) || defined(CONFIG_AVR32) || defined(COFNIG_NDS32) || \
+defined(CONFIG_SANDBOX) || defined(CONFIG_X86)
+       ulong start, end;
+       int i;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
+               start = bd->bi_dram[i].start;
+               end = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
+               if ((ulong)video_fb_address >= start &&
+                   (ulong)video_fb_address < end)
+                       return 1;
+       }
+#else
+       if ((ulong)video_fb_address >= bd->bi_memstart &&
+           (ulong)video_fb_address < bd->bi_memstart + bd->bi_memsize)
+               return 1;
+#endif
+       return 0;
+}
+
 static int video_init(void)
 {
        unsigned char color8;
 
-       if ((pGD = video_hw_init()) == NULL)
+       pGD = video_hw_init();
+       if (pGD == NULL)
                return -1;
 
        video_fb_address = (void *) VIDEO_FB_ADRS;
@@ -1663,6 +1721,8 @@ static int video_init(void)
        video_init_hw_cursor(VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
 #endif
 
+       cfb_do_flush_cache = cfb_fb_is_in_dram() && dcache_status();
+
        /* Init drawing pats */
        switch (VIDEO_DATA_FORMAT) {
        case GDF__8BIT_INDEX:
@@ -1736,7 +1796,7 @@ static int video_init(void)
 
 #ifdef CONFIG_VIDEO_LOGO
        /* Plot the logo and get start point of console */
-       PRINTD("Video: Drawing the logo ...\n");
+       debug("Video: Drawing the logo ...\n");
        video_console_address = video_logo();
 #else
        video_console_address = video_fb_address;
@@ -1775,7 +1835,7 @@ int drv_video_init(void)
        skip_dev_init = (video_init() == -1);
 
 #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
-       PRINTD("KBD: Keyboard init ...\n");
+       debug("KBD: Keyboard init ...\n");
        skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1);
 #endif