video: cfb_console: flush dcache for frame buffer in DRAM

Data cache flushing is required for frame buffer in RAM to fix the
distorted console text output. Currently this text distortion is
observed with cfb on beagleboard and N900 when running with data
cache enabled.

Reported-by: Pali Rohár <pali.rohar@gmail.com>
Tested-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index b38cbd4..92fa77d 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -360,6 +360,8 @@
 extern void video_get_info_str(int line_number,	char *info);
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Locals */
 static GraphicDevice *pGD;	/* Pointer to Graphic array */
 
@@ -377,6 +379,8 @@
 
 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,
@@ -553,6 +557,8 @@
 					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++;
 		}
@@ -621,6 +627,8 @@
 		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);
 		}
 	}
 }
@@ -716,6 +724,8 @@
 			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)
@@ -1675,6 +1685,29 @@
 }
 #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;
@@ -1688,6 +1721,8 @@
 	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: