fbcon: fix color generation for monochrome framebuffer
authorThomas Pfaff <tpfaff@pcs.com>
Wed, 6 Feb 2008 09:39:45 +0000 (01:39 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 6 Feb 2008 18:41:18 +0000 (10:41 -0800)
The current attr_fgcol_ec / attr_bgcol_ec macros do a simple shift of bits
to get the color from vc_video_erase_char.  For a monochrome display
however the attribute does not contain any color, only attribute bits.
Furthermore the reverse bit is lost because it is shifted out, the
resulting color is always 0.

This can bee seen on a monochrome console either directly or by setting it
to inverse mode via "setterm -inversescreen on" .  Text is written with
correct color, fb_fillrects from a bit_clear / bit_clear_margins will get
wrong colors.

Signed-off-by: Thomas Pfaff <tpfaff@pcs.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/video/console/bitblit.c
drivers/video/console/fbcon.c
drivers/video/console/fbcon.h
drivers/video/console/fbcon_ccw.c
drivers/video/console/fbcon_cw.c
drivers/video/console/fbcon_ud.c
drivers/video/console/tileblit.c
drivers/video/pmag-aa-fb.c

index 308850df16fea8bafaa7c610cf954f87fc7cd866..69864b1b3f9ee149aa7f2adbf2676574d09c8d49 100644 (file)
@@ -63,7 +63,7 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
        struct fb_fillrect region;
 
-       region.color = attr_bgcol_ec(bgshift, vc);
+       region.color = attr_bgcol_ec(bgshift, vc, info);
        region.dx = sx * vc->vc_font.width;
        region.dy = sy * vc->vc_font.height;
        region.width = width * vc->vc_font.width;
@@ -213,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
        unsigned int bs = info->var.yres - bh;
        struct fb_fillrect region;
 
-       region.color = attr_bgcol_ec(bgshift, vc);
+       region.color = attr_bgcol_ec(bgshift, vc, info);
        region.rop = ROP_COPY;
 
        if (rw && !bottom_only) {
index c6babb178c772e0020948b486512c97e1995e5bc..022282494d3fecee136f47d831e2dd4e534fe62d 100644 (file)
@@ -334,10 +334,7 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
        switch (depth) {
        case 1:
        {
-               int col = ~(0xfff << (max(info->var.green.length,
-                                         max(info->var.red.length,
-                                             info->var.blue.length)))) & 0xff;
-
+               int col = mono_col(info);
                /* 0 or 1 */
                int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0;
                int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col;
index 8e6ef4bc7a5c75027ae59c8b35b4c5c5acdaead0..3706307e70ed271ddc84d70f1c02ef66c9ff604e 100644 (file)
@@ -93,10 +93,6 @@ struct fbcon_ops {
        (((s) >> (fgshift)) & 0x0f)
 #define attr_bgcol(bgshift,s)    \
        (((s) >> (bgshift)) & 0x0f)
-#define        attr_bgcol_ec(bgshift,vc) \
-       ((vc) ? (((vc)->vc_video_erase_char >> (bgshift)) & 0x0f) : 0)
-#define attr_fgcol_ec(fgshift,vc) \
-       ((vc) ? (((vc)->vc_video_erase_char >> (fgshift)) & 0x0f) : 0)
 
 /* Monochrome */
 #define attr_bold(s) \
@@ -108,6 +104,49 @@ struct fbcon_ops {
 #define attr_blink(s) \
        ((s) & 0x8000)
        
+#define mono_col(info)                                                 \
+       (~(0xfff << (max((info)->var.green.length,                      \
+                        max((info)->var.red.length,                    \
+                            (info)->var.blue.length)))) & 0xff)
+
+static inline int attr_col_ec(int shift, struct vc_data *vc,
+                             struct fb_info *info, int is_fg)
+{
+       int is_mono01;
+       int col;
+       int fg;
+       int bg;
+
+       if (!vc)
+               return 0;
+
+       if (vc->vc_can_do_color)
+               return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char)
+                       : attr_bgcol(shift,vc->vc_video_erase_char);
+
+       if (!info)
+               return 0;
+
+       col = mono_col(info);
+       is_mono01 = info->fix.visual == FB_VISUAL_MONO01;
+
+       if (attr_reverse(vc->vc_video_erase_char)) {
+               fg = is_mono01 ? col : 0;
+               bg = is_mono01 ? 0 : col;
+       }
+       else {
+               fg = is_mono01 ? 0 : col;
+               bg = is_mono01 ? col : 0;
+       }
+
+       return is_fg ? fg : bg;
+}
+
+#define attr_bgcol_ec(bgshift,vc,info)         \
+       attr_col_ec(bgshift,vc,info,0);
+#define attr_fgcol_ec(fgshift,vc,info)         \
+       attr_col_ec(fgshift,vc,info,1);
+
 /* Font */
 #define REFCOUNT(fd)   (((int *)(fd))[-1])
 #define FNTSIZE(fd)    (((int *)(fd))[-2])
index 825e6d6972a72cbecb51a1194fcdaf16f0cf0a7e..bdf913ecf001de64916ede55b21c9b318743ee04 100644 (file)
@@ -84,7 +84,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
        u32 vyres = GETVYRES(ops->p->scrollmode, info);
 
-       region.color = attr_bgcol_ec(bgshift,vc);
+       region.color = attr_bgcol_ec(bgshift,vc,info);
        region.dx = sy * vc->vc_font.height;
        region.dy = vyres - ((sx + width) * vc->vc_font.width);
        region.height = width * vc->vc_font.width;
@@ -198,7 +198,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
        struct fb_fillrect region;
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 
-       region.color = attr_bgcol_ec(bgshift,vc);
+       region.color = attr_bgcol_ec(bgshift,vc,info);
        region.rop = ROP_COPY;
 
        if (rw && !bottom_only) {
index c637e6318803796e6b735b2f860227543cd0107d..a6819b9d1770cccd2690e9ee4c95f52736c27d42 100644 (file)
@@ -70,7 +70,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
        u32 vxres = GETVXRES(ops->p->scrollmode, info);
 
-       region.color = attr_bgcol_ec(bgshift,vc);
+       region.color = attr_bgcol_ec(bgshift,vc,info);
        region.dx = vxres - ((sy + height) * vc->vc_font.height);
        region.dy = sx *  vc->vc_font.width;
        region.height = width * vc->vc_font.width;
@@ -182,7 +182,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
        struct fb_fillrect region;
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 
-       region.color = attr_bgcol_ec(bgshift,vc);
+       region.color = attr_bgcol_ec(bgshift,vc,info);
        region.rop = ROP_COPY;
 
        if (rw && !bottom_only) {
index 1473506df5d0654cba5d2bf6e5281ccc6b186870..d9b5d6eb68a73c4e9129a84679532dc191cf4693 100644 (file)
@@ -71,7 +71,7 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
        u32 vyres = GETVYRES(ops->p->scrollmode, info);
        u32 vxres = GETVXRES(ops->p->scrollmode, info);
 
-       region.color = attr_bgcol_ec(bgshift,vc);
+       region.color = attr_bgcol_ec(bgshift,vc,info);
        region.dy = vyres - ((sy + height) * vc->vc_font.height);
        region.dx = vxres - ((sx + width) *  vc->vc_font.width);
        region.width = width * vc->vc_font.width;
@@ -228,7 +228,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
        struct fb_fillrect region;
        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 
-       region.color = attr_bgcol_ec(bgshift,vc);
+       region.color = attr_bgcol_ec(bgshift,vc,info);
        region.rop = ROP_COPY;
 
        if (rw && !bottom_only) {
index d981fe4d86c6b18dc5396dc99a032b5f02ca455d..0056a41e5c35c2a3d323c69845a2db895a080108 100644 (file)
@@ -40,8 +40,8 @@ static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy,
 
        rect.index = vc->vc_video_erase_char &
                ((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
-       rect.fg = attr_fgcol_ec(fgshift, vc);
-       rect.bg = attr_bgcol_ec(bgshift, vc);
+       rect.fg = attr_fgcol_ec(fgshift, vc, info);
+       rect.bg = attr_bgcol_ec(bgshift, vc, info);
        rect.sx = sx;
        rect.sy = sy;
        rect.width = width;
index a864438b6008bcde0d9baba19821f13fff1b6435..6515ec11c16ba250f55f6cbe6a10b6a74f7effca 100644 (file)
@@ -150,7 +150,7 @@ static int aafbcon_set_font(struct display *disp, int width, int height)
 {
        struct aafb_info *info = (struct aafb_info *)disp->fb_info;
        struct aafb_cursor *c = &info->cursor;
-       u8 fgc = ~attr_bgcol_ec(disp, disp->conp);
+       u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info);
 
        if (width > 64 || height > 64 || width < 0 || height < 0)
                return -EINVAL;