diff --git a/target/linux/xburst/patches-2.6.32/450-fbcon-color-fonts.patch b/target/linux/xburst/patches-2.6.32/450-fbcon-color-fonts.patch new file mode 100644 index 000000000..0f0ee8cc3 --- /dev/null +++ b/target/linux/xburst/patches-2.6.32/450-fbcon-color-fonts.patch @@ -0,0 +1,300 @@ +--- ./drivers/char/vt.c.orig 2010-03-16 04:52:04.000000000 +1300 ++++ ./drivers/char/vt.c 2010-07-13 00:00:34.000000000 +1200 +@@ -3894,6 +3894,7 @@ + struct console_font font; + int rc = -EINVAL; + int size; ++ u8 std_font = *((u32*)op->data) != 0x6a127efd; + + if (vc->vc_mode != KD_TEXT) + return -EINVAL; +@@ -3923,7 +3924,7 @@ + } + if (op->width <= 0 || op->width > 32 || op->height > 32) + return -EINVAL; +- size = (op->width+7)/8 * 32 * op->charcount; ++ size = ( std_font ? (op->width+7)/8 * 32 : 4 * op->width * op->height) * op->charcount; + if (size > max_font_size) + return -ENOSPC; + font.charcount = op->charcount; +--- ./drivers/video/console/bitblit.c.orig 2010-07-01 11:30:17.000000000 +1200 ++++ ./drivers/video/console/bitblit.c 2010-07-15 21:12:13.000000000 +1200 +@@ -110,6 +110,12 @@ + info->fbops->fb_imageblit(info, image); + } + ++/* info: details of the framebuffer ++ * image: the off-screen image in which the character (sub)string is being ++ * prepared ++ * dst: a pointer to the top-left pixel in the off-screen image where the ++ * character (sub)string should go ++ */ + static inline void bit_putcs_unaligned(struct vc_data *vc, + struct fb_info *info, const u16 *s, + u32 attr, u32 cnt, u32 d_pitch, +@@ -145,12 +151,62 @@ + + } + ++void inline draw_glyph_row_inv( int pixels_across_glyph, u8 *src, u8 *target) { ++ u32 *pixel_on_glyph_sheet = (u32*) src; ++ u32 *pixel_on_screen = (u32*) target; ++ ++ while( pixels_across_glyph--) { ++ *pixel_on_screen = ~(*pixel_on_glyph_sheet); ++ ++ pixel_on_glyph_sheet; ++ ++ pixel_on_screen; ++ } ++} ++ ++void inline draw_glyph_row_75( int pixels_across_glyph, u8 *src, u8 *target) { ++ u32 pixel; ++ u32 *pixel_on_glyph_sheet = (u32*) src; ++ u32 *pixel_on_screen = (u32*) target; ++ /* Copy the pixels at 75% brightness */ ++ while( pixels_across_glyph--) { ++ pixel = *pixel_on_glyph_sheet; ++ /* This is a cheeky way of multiplying by 0.75 */ ++ pixel = ( pixel >> 1) & 0x7f7f7f7f; ++ pixel += ( pixel >> 1) & 0x7f7f7f7f; ++ *pixel_on_screen = pixel; ++ ++ pixel_on_glyph_sheet; ++ ++ pixel_on_screen; ++ } ++} ++ ++/* ++ * width: the number of bytes required to store a single row of pixels from ++ * a glyph ++ * cellsize: the number of bytes required to store the pixels for a single ++ * glyph ++ * maxcnt: the maximum number of characters that can be blasted to the screen ++ * at one time ( limited by the amount of video RAM available for a ++ * (sub)string of characters) ++ * The NanoNote has 32-bits per pixel arranged BGRA ++ * info->fix.line_length: the number of bytes to advance through the frame ++ * buffer in order to get from the address of a pixel to ++ * the address of the pixel directly below it ++ * screen_row_hop: the number of 32-bit words to advance through the frame ++ * buffer in order to get from the address of a pixel to the ++ * address of the pixel directly below it on the screen ++ * glyph_on_screen: the address of the pixel on screen where the top-left of ++ * the next glyph should go ++ * row_on_screen: the address of the pixel on screen where the next row of ++ * pixels from the glyph should go ++ * row_on_glyph_sheet: pointer within font.data ( the glyph sheet) of the ++ * left-most pixel from the next row to be drawn ++ */ + static void bit_putcs(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg) + { + struct fb_image image; +- u32 width = DIV_ROUND_UP(vc->vc_font.width, 8); ++ u8 std_font = *((u32*)vc->vc_font.data) != 0x6a127efd; ++ u32 width = std_font ? DIV_ROUND_UP(vc->vc_font.width, 8) : 4 * vc->vc_font.width; + u32 cellsize = width * vc->vc_font.height; + u32 maxcnt = info->pixmap.size/cellsize; + u32 scan_align = info->pixmap.scan_align - 1; +@@ -158,6 +214,10 @@ + u32 mod = vc->vc_font.width % 8, cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; ++ u32 screen_row_hop; ++ u16 charmask; ++ u8 *row_on_glyph_sheet, *glyph_on_screen, *row_on_screen; ++ u8 code_point, rows_left; + + image.fg_color = fg; + image.bg_color = bg; +@@ -172,31 +232,73 @@ + return; + } + +- while (count) { +- if (count > maxcnt) +- cnt = maxcnt; +- else +- cnt = count; +- +- image.width = vc->vc_font.width * cnt; +- pitch = DIV_ROUND_UP(image.width, 8) + scan_align; +- pitch &= ~scan_align; +- size = pitch * image.height + buf_align; +- size &= ~buf_align; +- dst = fb_get_buffer_offset(info, &info->pixmap, size); +- image.data = dst; +- +- if (!mod) +- bit_putcs_aligned(vc, info, s, attribute, cnt, pitch, +- width, cellsize, &image, buf, dst); +- else +- bit_putcs_unaligned(vc, info, s, attribute, cnt, +- pitch, width, cellsize, &image, +- buf, dst); +- +- image.dx += cnt * vc->vc_font.width; +- count -= cnt; +- s += cnt; ++ if ( std_font) { ++ while (count) { ++ if (count > maxcnt) ++ cnt = maxcnt; ++ else ++ cnt = count; ++ ++ image.width = vc->vc_font.width * cnt; ++ pitch = DIV_ROUND_UP(image.width, 8) + scan_align; ++ pitch &= ~scan_align; ++ size = pitch * image.height + buf_align; ++ size &= ~buf_align; ++ dst = fb_get_buffer_offset(info, &info->pixmap, size); ++ image.data = dst; ++ ++ if (!mod) ++ bit_putcs_aligned(vc, info, s, attribute, cnt, ++ pitch, width, cellsize, ++ &image, buf, dst); ++ else ++ bit_putcs_unaligned(vc, info, s, attribute, cnt, ++ pitch, width, cellsize, ++ &image, buf, dst); ++ ++ image.dx += cnt * vc->vc_font.width; ++ count -= cnt; ++ s += cnt; ++ } ++ } ++ else { /* The font is not a standard 1-bit font */ ++ charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; ++ screen_row_hop = info->fix.line_length; ++ glyph_on_screen = info->screen_base + ++ screen_row_hop * image.dy + ++ 4 * image.dx; ++ /* While there are still characters to draw.. */ ++ while (count--) { ++ code_point = scr_readw(s++) & charmask; ++ row_on_glyph_sheet = vc->vc_font.data + ++ cellsize * code_point; ++ /* Draw every row of the glyph */ ++ row_on_screen = glyph_on_screen; ++ rows_left = vc->vc_font.height; ++ while( rows_left--) ++ { ++ /* If the background color is NOT black then do ++ * reverse video */ ++ if ( 0 < bg) { ++ draw_glyph_row_inv( vc->vc_font.width, ++ row_on_glyph_sheet, ++ row_on_screen); ++ } ++ /* If the foreground color is high-intensity */ ++ else if ( 8 <= fg) { ++ memcpy( row_on_screen, ++ row_on_glyph_sheet, width); ++ } ++ else { ++ draw_glyph_row_75( vc->vc_font.width, ++ row_on_glyph_sheet, ++ row_on_screen); ++ } ++ row_on_glyph_sheet += width; ++ row_on_screen += screen_row_hop; ++ } ++ glyph_on_screen += width; ++ } + } + + /* buf is always NULL except when in monochrome mode, so in this case +@@ -239,6 +341,29 @@ + } + } + ++static void bgra_cursor( struct vc_data *vc, struct fb_info *info, short c, ++ struct fb_cursor *cursor) ++{ ++ u32 x = cursor->image.dx; ++ u32 y = cursor->image.dy; ++ u32 gw = vc->vc_font.width; ++ u32 gh = vc->vc_font.height; ++ u32 *pixel; ++ ++ /* Draw the glyph to the screen */ ++ bit_putcs( vc, info, &c, 1, y/gh, x/gw, 0, 0); ++ ++ if ( cursor->enable) { ++ /* Invert the last row of pixels */ ++ pixel = (u32*) ( info->screen_base + ++ info->fix.line_length * ( y + gh - 1) + 4 * x); ++ while ( gw--) { ++ *pixel ^= 0xffffffff; ++ ++ pixel; ++ } ++ } ++} ++ + static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int softback_lines, int fg, int bg) + { +@@ -250,6 +375,7 @@ + int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1; + char *src; ++ u8 std_font = *((u32*)vc->vc_font.data) != 0x6a127efd; + + cursor.set = 0; + +@@ -388,8 +514,14 @@ + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + +- if (err) +- soft_cursor(info, &cursor); ++ if (err) { ++ if ( std_font) { ++ soft_cursor(info, &cursor); ++ } ++ else { ++ bgra_cursor( vc, info, c, &cursor); ++ } ++ } + + ops->cursor_reset = 0; + } +--- ./drivers/video/console/fbcon.c.orig 2010-07-12 23:19:39.000000000 +1200 ++++ ./drivers/video/console/fbcon.c 2010-07-13 20:18:41.000000000 +1200 +@@ -2528,7 +2528,8 @@ + int size; + int i, csum; + u8 *new_data, *data = font->data; +- int pitch = (font->width+7) >> 3; ++ u8 std_font = *((u32*)data) != 0x6a127efd; ++ int pitch = std_font ? (font->width+7) >> 3 : 4 * font->width; + + /* Is there a reason why fbconsole couldn't handle any charcount >256? + * If not this check should be changed to charcount < 256 */ +@@ -2547,6 +2548,7 @@ + size = h * pitch * charcount; + + new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER); ++ DPRINTK(KERN_INFO "fbcon_set_font size:%d\n", size); + + if (!new_data) + return -ENOMEM; +@@ -2555,8 +2557,14 @@ + FNTSIZE(new_data) = size; + FNTCHARCNT(new_data) = charcount; + REFCOUNT(new_data) = 0; /* usage counter */ +- for (i=0; i< charcount; i++) { +- memcpy(new_data + i*h*pitch, data + i*32*pitch, h*pitch); ++ if ( std_font) { ++ for (i=0; i< charcount; i++) { ++ memcpy(new_data + i*h*pitch, data + i*32*pitch, ++ h*pitch); ++ } ++ } ++ else { ++ memcpy( new_data, data, size); + } + + /* Since linux has a nice crc32 function use it for counting font