Commit 455f8c02 authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbcon: Disable fbcon cursor if vt softcursor is enabled

Problem reported by Gerd Knorr:

  (1) boot with vesafb (thats what I'm using, maybe it shows on other
      framebuffers and/or vgacon as well).
  (2) login into one terminal, then type "echo -ne '\033[?17;15;239c'".
      You should have a nice, yellow and *not* blinking cursor block.
      That is what I have in my .profile because I can't stand the
      blinking cursors.
  (3) Switch to another terminal.  The cursor goes into blinking
      underscore mode now (i.e. the default cursor).
  (4) Switch back to the first terminal.  Now you have a yellow block
      with the last two pixel lines (i.e. the underscore) blinking.

This bug is caused by both fbcon_cursor and vt softcursor being active at
the same time.

Fix:

- Disable fbcon_cursor if vt softcursor is active (vc->vc_cursor_type &
  0x10) != 0.

- Recheck/reload fbcon cursor for each vt switch
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 e35b71b0
...@@ -243,7 +243,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ...@@ -243,7 +243,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
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); int y = real_y(p, vc->vc_y);
int attribute; int attribute, use_sw = (vc->vc_cursor_type & 0x10);
char *src; char *src;
cursor.set = 0; cursor.set = 0;
...@@ -252,7 +252,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ...@@ -252,7 +252,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
attribute = get_attribute(info, c); attribute = get_attribute(info, c);
src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height)); src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
if (ops->cursor_state.image.data != src) { if (ops->cursor_state.image.data != src ||
ops->cursor_reset) {
ops->cursor_state.image.data = src; ops->cursor_state.image.data = src;
cursor.set |= FB_CUR_SETIMAGE; cursor.set |= FB_CUR_SETIMAGE;
} }
...@@ -271,34 +272,39 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ...@@ -271,34 +272,39 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
} }
if (ops->cursor_state.image.fg_color != fg || if (ops->cursor_state.image.fg_color != fg ||
ops->cursor_state.image.bg_color != bg) { ops->cursor_state.image.bg_color != bg ||
ops->cursor_reset) {
ops->cursor_state.image.fg_color = fg; ops->cursor_state.image.fg_color = fg;
ops->cursor_state.image.bg_color = bg; ops->cursor_state.image.bg_color = bg;
cursor.set |= FB_CUR_SETCMAP; cursor.set |= FB_CUR_SETCMAP;
} }
if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) || if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) ||
(ops->cursor_state.image.dy != (vc->vc_font.height * y))) { (ops->cursor_state.image.dy != (vc->vc_font.height * y)) ||
ops->cursor_reset) {
ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x; ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x;
ops->cursor_state.image.dy = vc->vc_font.height * y; ops->cursor_state.image.dy = vc->vc_font.height * y;
cursor.set |= FB_CUR_SETPOS; cursor.set |= FB_CUR_SETPOS;
} }
if (ops->cursor_state.image.height != vc->vc_font.height || if (ops->cursor_state.image.height != vc->vc_font.height ||
ops->cursor_state.image.width != vc->vc_font.width) { ops->cursor_state.image.width != vc->vc_font.width ||
ops->cursor_reset) {
ops->cursor_state.image.height = vc->vc_font.height; ops->cursor_state.image.height = vc->vc_font.height;
ops->cursor_state.image.width = vc->vc_font.width; ops->cursor_state.image.width = vc->vc_font.width;
cursor.set |= FB_CUR_SETSIZE; cursor.set |= FB_CUR_SETSIZE;
} }
if (ops->cursor_state.hot.x || ops->cursor_state.hot.y) { if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
ops->cursor_reset) {
ops->cursor_state.hot.x = cursor.hot.y = 0; ops->cursor_state.hot.x = cursor.hot.y = 0;
cursor.set |= FB_CUR_SETHOT; cursor.set |= FB_CUR_SETHOT;
} }
if ((cursor.set & FB_CUR_SETSIZE) || if (cursor.set & FB_CUR_SETSIZE ||
((vc->vc_cursor_type & 0x0f) != p->cursor_shape) vc->vc_cursor_type != p->cursor_shape ||
|| ops->cursor_state.mask == NULL) { ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
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;
...@@ -309,10 +315,11 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ...@@ -309,10 +315,11 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
if (ops->cursor_state.mask) if (ops->cursor_state.mask)
kfree(ops->cursor_state.mask); kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask; ops->cursor_state.mask = mask;
p->cursor_shape = vc->vc_cursor_type & 0x0f;
p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE; cursor.set |= FB_CUR_SETSHAPE;
switch (vc->vc_cursor_type & 0x0f) { switch (p->cursor_shape & CUR_HWMASK) {
case CUR_NONE: case CUR_NONE:
cur_height = 0; cur_height = 0;
break; break;
...@@ -348,7 +355,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ...@@ -348,7 +355,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
case CM_DRAW: case CM_DRAW:
case CM_MOVE: case CM_MOVE:
default: default:
ops->cursor_state.enable = 1; ops->cursor_state.enable = (use_sw) ? 0 : 1;
break; break;
} }
...@@ -367,6 +374,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ...@@ -367,6 +374,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
cursor.rop = ROP_XOR; cursor.rop = ROP_XOR;
info->fbops->fb_cursor(info, &cursor); info->fbops->fb_cursor(info, &cursor);
ops->cursor_reset = 0;
} }
void fbcon_set_bitops(struct fbcon_ops *ops) void fbcon_set_bitops(struct fbcon_ops *ops)
......
...@@ -1889,6 +1889,7 @@ static int fbcon_switch(struct vc_data *vc) ...@@ -1889,6 +1889,7 @@ static int fbcon_switch(struct vc_data *vc)
int i, prev_console, do_set_par = 0; int i, prev_console, do_set_par = 0;
info = registered_fb[con2fb_map[vc->vc_num]]; info = registered_fb[con2fb_map[vc->vc_num]];
if (softback_top) { if (softback_top) {
int l = fbcon_softback_size / vc->vc_size_row; int l = fbcon_softback_size / vc->vc_size_row;
if (softback_lines) if (softback_lines)
...@@ -1904,6 +1905,7 @@ static int fbcon_switch(struct vc_data *vc) ...@@ -1904,6 +1905,7 @@ static int fbcon_switch(struct vc_data *vc)
softback_top = 0; softback_top = 0;
} }
} }
if (logo_shown >= 0) { if (logo_shown >= 0) {
struct vc_data *conp2 = vc_cons[logo_shown].d; struct vc_data *conp2 = vc_cons[logo_shown].d;
...@@ -1953,6 +1955,7 @@ static int fbcon_switch(struct vc_data *vc) ...@@ -1953,6 +1955,7 @@ static int fbcon_switch(struct vc_data *vc)
} }
set_blitting_type(vc, info, p); set_blitting_type(vc, info, p);
((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
vc->vc_can_do_color = (fb_get_color_depth(info) != 1); vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
......
...@@ -65,6 +65,7 @@ struct fbcon_ops { ...@@ -65,6 +65,7 @@ struct fbcon_ops {
struct fb_cursor cursor_state; struct fb_cursor cursor_state;
int currcon; /* Current VC. */ int currcon; /* Current VC. */
int cursor_flash; int cursor_flash;
int cursor_reset;
char *cursor_data; char *cursor_data;
}; };
/* /*
......
...@@ -84,10 +84,11 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, ...@@ -84,10 +84,11 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info,
struct display *p, int mode, int fg, int bg) struct display *p, int mode, int fg, int bg)
{ {
struct fb_tilecursor cursor; struct fb_tilecursor cursor;
int use_sw = (vc->vc_cursor_type & 0x01);
cursor.sx = vc->vc_x; cursor.sx = vc->vc_x;
cursor.sy = vc->vc_y; cursor.sy = vc->vc_y;
cursor.mode = (mode == CM_ERASE) ? 0 : 1; cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1;
cursor.fg = fg; cursor.fg = fg;
cursor.bg = bg; cursor.bg = bg;
......
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