Commit 216f473e authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbdev: support for bold attribute for monochrome framebuffers

This patch adds support for the bold attribute for monochrome framebuffers.
 This fixes a regression from 2.4 where bold, underline and reverse
attributes are supported.
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 37455dc6
...@@ -408,7 +408,6 @@ int set_con2fb_map(int unit, int newidx) ...@@ -408,7 +408,6 @@ int set_con2fb_map(int unit, int newidx)
static inline int get_color(struct vc_data *vc, struct fb_info *info, static inline int get_color(struct vc_data *vc, struct fb_info *info,
u16 c, int is_fg) u16 c, int is_fg)
{ {
struct display *p = &fb_display[fg_console];
int depth = fb_get_color_depth(info); int depth = fb_get_color_depth(info);
int color = 0; int color = 0;
...@@ -422,9 +421,8 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, ...@@ -422,9 +421,8 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
/* 0 or 1 */ /* 0 or 1 */
int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0; int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0;
int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1; int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1;
int reverse = attr_reverse(c, p->inverse);
color = (is_fg) ? (reverse) ? bg : fg : (reverse) ? fg : bg; color = (is_fg) ? fg : bg;
break; break;
} }
case 2: case 2:
...@@ -447,13 +445,45 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, ...@@ -447,13 +445,45 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
return color; return color;
} }
static inline int is_underline(struct fb_info *info, u16 c) #define FBCON_ATTRIBUTE_UNDERLINE 1
#define FBCON_ATTRIBUTE_REVERSE 2
#define FBCON_ATTRIBUTE_BOLD 4
static inline int get_attribute(struct fb_info *info, u16 c)
{ {
int underline = 0; int attribute = 0;
if (fb_get_color_depth(info) == 1) {
if (attr_underline(c))
attribute |= FBCON_ATTRIBUTE_UNDERLINE;
if (attr_reverse(c))
attribute |= FBCON_ATTRIBUTE_REVERSE;
if (attr_bold(c))
attribute |= FBCON_ATTRIBUTE_BOLD;
}
return attribute;
}
if (fb_get_color_depth(info) == 1) static inline void update_attr(u8 *dst, u8 *src, int attribute,
underline = attr_underline(c); struct vc_data *vc)
return underline; {
int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
int width = (vc->vc_font.width + 7) >> 3;
unsigned int cellsize = vc->vc_font.height * width;
u8 c;
offset = cellsize - (offset * width);
for (i = 0; i < cellsize; i++) {
c = src[i];
if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i >= offset)
c = 0xff;
if (attribute & FBCON_ATTRIBUTE_BOLD)
c |= c >> 1;
if (attribute & FBCON_ATTRIBUTE_REVERSE)
c = ~c;
dst[i] = c;
}
} }
void accel_bmove(struct vc_data *vc, struct fb_info *info, int sy, void accel_bmove(struct vc_data *vc, struct fb_info *info, int sy,
...@@ -506,11 +536,11 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info, ...@@ -506,11 +536,11 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info,
unsigned int shift_low = 0, mod = vc->vc_font.width % 8; unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
unsigned int shift_high = 8, pitch, cnt, size, k; unsigned int shift_high = 8, pitch, cnt, size, k;
unsigned int idx = vc->vc_font.width >> 3; unsigned int idx = vc->vc_font.width >> 3;
unsigned int underline = is_underline(info, scr_readw(s)); unsigned int attribute = get_attribute(info, scr_readw(s));
struct fb_image image; struct fb_image image;
u8 *src, *dst, *buf = NULL; u8 *src, *dst, *buf = NULL;
if (underline) { if (attribute) {
buf = kmalloc(cellsize, GFP_KERNEL); buf = kmalloc(cellsize, GFP_KERNEL);
if (!buf) if (!buf)
return; return;
...@@ -549,17 +579,14 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info, ...@@ -549,17 +579,14 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info,
src = vc->vc_font.data + (scr_readw(s++)& src = vc->vc_font.data + (scr_readw(s++)&
charmask)*cellsize; charmask)*cellsize;
if (underline) { if (attribute) {
int offset = (vc->vc_font.height < 10) ? 1 : 2; update_attr(buf, src, attribute, vc);
memcpy(buf, src, cellsize);
memset(buf + cellsize - offset, 0xff,
offset * width);
src = buf; src = buf;
} }
move_unaligned(info, &info->pixmap, dst, pitch, move_unaligned(info, &info->pixmap, dst, pitch,
src, idx, image.height, src, idx, image.height,
shift_high, shift_low, mod); shift_high, shift_low, mod);
shift_low += mod; shift_low += mod;
dst += (shift_low >= 8) ? width : width - 1; dst += (shift_low >= 8) ? width : width - 1;
shift_low &= 7; shift_low &= 7;
...@@ -569,16 +596,14 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info, ...@@ -569,16 +596,14 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info,
while (k--) { while (k--) {
src = vc->vc_font.data + (scr_readw(s++)& src = vc->vc_font.data + (scr_readw(s++)&
charmask)*cellsize; charmask)*cellsize;
if (underline) {
int offset = (vc->vc_font.height < 10) ? 1 : 2;
memcpy(buf, src, cellsize); if (attribute) {
memset(buf + cellsize - offset, 0xff, update_attr(buf, src, attribute, vc);
offset * width);
src = buf; src = buf;
} }
move_aligned(info, &info->pixmap, dst, pitch, move_aligned(info, &info->pixmap, dst, pitch,
src, idx, image.height); src, idx, image.height);
dst += width; dst += width;
} }
} }
...@@ -586,7 +611,9 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info, ...@@ -586,7 +611,9 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info,
image.dx += cnt * vc->vc_font.width; image.dx += cnt * vc->vc_font.width;
count -= cnt; count -= cnt;
} }
kfree(buf);
if (buf)
kfree(buf);
} }
void accel_clear_margins(struct vc_data *vc, struct fb_info *info, void accel_clear_margins(struct vc_data *vc, struct fb_info *info,
...@@ -1074,14 +1101,15 @@ static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) ...@@ -1074,14 +1101,15 @@ static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
static void fbcon_cursor(struct vc_data *vc, int mode) static void fbcon_cursor(struct vc_data *vc, int mode)
{ {
struct fb_cursor cursor;
struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]]; struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
struct display *p = &fb_display[vc->vc_num]; struct display *p = &fb_display[vc->vc_num];
int w = (vc->vc_font.width + 7) >> 3, c; int w = (vc->vc_font.width + 7) >> 3, c;
int y = real_y(p, vc->vc_y), fg, bg; int y = real_y(p, vc->vc_y), fg, bg;
int underline; int attribute;
struct fb_cursor cursor; u8 *src;
if (mode & CM_SOFTBACK) { if (mode & CM_SOFTBACK) {
mode &= ~CM_SOFTBACK; mode &= ~CM_SOFTBACK;
if (softback_lines) { if (softback_lines) {
...@@ -1094,8 +1122,22 @@ static void fbcon_cursor(struct vc_data *vc, int mode) ...@@ -1094,8 +1122,22 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
fbcon_set_origin(vc); fbcon_set_origin(vc);
c = scr_readw((u16 *) vc->vc_pos); c = scr_readw((u16 *) vc->vc_pos);
underline = is_underline(info, c); attribute = get_attribute(info, c);
cursor.image.data = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height)); src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
if (attribute) {
u8 *dst;
dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
if (!dst)
return;
if (info->cursor.data)
kfree(info->cursor.data);
info->cursor.data = dst;
update_attr(dst, src, attribute, vc);
src = dst;
}
cursor.image.data = src;
cursor.set = FB_CUR_SETCUR; cursor.set = FB_CUR_SETCUR;
cursor.image.depth = 1; cursor.image.depth = 1;
...@@ -1139,24 +1181,19 @@ static void fbcon_cursor(struct vc_data *vc, int mode) ...@@ -1139,24 +1181,19 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
cursor.set |= FB_CUR_SETHOT; cursor.set |= FB_CUR_SETHOT;
} }
if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape) if ((cursor.set & FB_CUR_SETSIZE) ||
|| info->cursor.mask == NULL || info->cursor.ul != attr_underline(c) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
info->cursor.rev != attr_reverse(c, p->inverse)) { || info->cursor.mask == NULL) {
char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
int cur_height, size, i = 0; int cur_height, size, i = 0;
u8 msk = 0xff; u8 msk = 0xff;
if (!mask) return; if (!mask)
return;
if (info->cursor.mask) if (info->cursor.mask)
kfree(info->cursor.mask); kfree(info->cursor.mask);
info->cursor.mask = mask; info->cursor.mask = mask;
info->cursor.ul = attr_underline(c);
info->cursor.rev = attr_reverse(c, p->inverse);
if (info->cursor.rev)
msk = 0;
p->cursor_shape = vc->vc_cursor_type & 0x0f; p->cursor_shape = vc->vc_cursor_type & 0x0f;
cursor.set |= FB_CUR_SETSHAPE; cursor.set |= FB_CUR_SETSHAPE;
...@@ -1185,10 +1222,6 @@ static void fbcon_cursor(struct vc_data *vc, int mode) ...@@ -1185,10 +1222,6 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
while (size--) while (size--)
mask[i++] = ~msk; mask[i++] = ~msk;
size = cur_height * w; size = cur_height * w;
if (info->cursor.ul)
msk = ~msk;
if (info->cursor.ul)
msk = ~msk;
while (size--) while (size--)
mask[i++] = msk; mask[i++] = msk;
} }
......
...@@ -69,8 +69,8 @@ extern int set_con2fb_map(int unit, int newidx); ...@@ -69,8 +69,8 @@ extern int set_con2fb_map(int unit, int newidx);
/* Monochrome */ /* Monochrome */
#define attr_bold(s) \ #define attr_bold(s) \
((s) & 0x200) ((s) & 0x200)
#define attr_reverse(s, inverse) \ #define attr_reverse(s) \
(((s) & 0x800) ^ (inverse ? 0x800 : 0)) ((s) & 0x800)
#define attr_underline(s) \ #define attr_underline(s) \
((s) & 0x400) ((s) & 0x400)
#define attr_blink(s) \ #define attr_blink(s) \
......
...@@ -981,13 +981,14 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite) ...@@ -981,13 +981,14 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
if (copy_from_user(&cursor_user, sprite, sizeof(struct fb_cursor_user))) if (copy_from_user(&cursor_user, sprite, sizeof(struct fb_cursor_user)))
return -EFAULT; return -EFAULT;
memcpy(&cursor, &cursor_user, sizeof(cursor)); memcpy(&cursor, &cursor_user, sizeof(cursor_user));
cursor.mask = NULL; cursor.mask = NULL;
cursor.image.data = NULL; cursor.image.data = NULL;
cursor.image.cmap.red = NULL; cursor.image.cmap.red = NULL;
cursor.image.cmap.green = NULL; cursor.image.cmap.green = NULL;
cursor.image.cmap.blue = NULL; cursor.image.cmap.blue = NULL;
cursor.image.cmap.transp = NULL; cursor.image.cmap.transp = NULL;
cursor.data = NULL;
if (cursor.set & FB_CUR_SETCUR) if (cursor.set & FB_CUR_SETCUR)
info->cursor.enable = 1; info->cursor.enable = 1;
......
...@@ -383,11 +383,11 @@ struct fb_cursor { ...@@ -383,11 +383,11 @@ struct fb_cursor {
__u16 set; /* what to set */ __u16 set; /* what to set */
__u16 enable; /* cursor on/off */ __u16 enable; /* cursor on/off */
__u16 rop; /* bitop operation */ __u16 rop; /* bitop operation */
__u16 ul; /* underlined? */
__u16 rev; /* reversed? */
const char *mask; /* cursor mask bits */ const char *mask; /* cursor mask bits */
struct fbcurpos hot; /* cursor hot spot */ struct fbcurpos hot; /* cursor hot spot */
struct fb_image image; /* Cursor image */ struct fb_image image; /* Cursor image */
/* all fields below are for fbcon use only */
char *data; /* copy of bitmap */
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment