Commit f032365d authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbcon: refinements for fbcon

1.  From Petr Vandrovec <vandrove@vc.cvut.cz>.

Begin quote

        yesterday I finally found why 2.6.x has problems with taking
        over vgacon.  Problem is that take_over_console does:

  	if (IS_VISIBLE)
    	save_screen(i);
  	...
  	visual_init(i, 0);
  	...

        so code nicely saves screen contents, and calls visual_init,
        which calls fbcon's init, which in turn can issue vc_resize.  And this
        vc_resize will trigger read from vc->vc_origin.  But vc_origin still
        points to videomemory, not to the buffer where save_screen() copied
        its data.

End quote

So updating vc->vc_origin to point to screenbuf after the previous console
deinitializes allows fbcon to correctly update the screen from the screen
buffer.  This change makes the clearing of vram (using fillrect) unnecessary.

2.  If FBINFO_MISC_MODESWITCH flag is set in info, do the set_par() in
fbcon_switch() instead of piggy-backing the set_par() on fbcon_resize().  This
preserves the current var, skipping the unnecessary fb_find_mode() step.
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 253c89da
......@@ -2711,6 +2711,10 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
save_screen(i);
old_was_color = vc_cons[i].d->vc_can_do_color;
vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
origin = (unsigned long) screenbuf;
visible_origin = origin;
scr_end = origin + screenbuf_size;
pos = origin + video_size_row*y + 2*x;
visual_init(i, 0);
update_attr(i);
......
......@@ -815,14 +815,14 @@ static void fbcon_init(struct vc_data *vc, int init)
vc->vc_pos += logo_lines * vc->vc_size_row;
}
}
if (CON_IS_VISIBLE(vc) && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
accel_clear_margins(vc, info, 0);
update_screen(vc->vc_num);
}
scr_memsetw((unsigned short *) vc->vc_origin,
vc->vc_video_erase_char,
vc->vc_size_row * logo_lines);
if (CON_IS_VISIBLE(vc) && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
accel_clear_margins(vc, info, 0);
update_screen(vc->vc_num);
}
if (save) {
q = (unsigned short *) (vc->vc_origin +
vc->vc_size_row *
......@@ -1698,14 +1698,10 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
var.yres = height * fh;
x_diff = info->var.xres - var.xres;
y_diff = info->var.yres - var.yres;
if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh) ||
(info->flags & FBINFO_MISC_MODESWITCH)) {
if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) {
char mode[40];
DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
if (!info->fbops->fb_set_par)
return -EINVAL;
snprintf(mode, 40, "%ix%i", var.xres, var.yres);
err = fb_find_mode(&var, info, mode, info->monspecs.modedb,
info->monspecs.modedb_len, NULL,
......@@ -1715,11 +1711,10 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
DPRINTK("resize now %ix%i\n", var.xres, var.yres);
if (CON_IS_VISIBLE(vc)) {
var.activate = FB_ACTIVATE_NOW |
(info->flags & FBINFO_MISC_MODESWITCH) ?
FB_ACTIVATE_FORCE : 0;
FB_ACTIVATE_FORCE;
fb_set_var(info, &var);
info->flags &= ~FBINFO_MISC_MODESWITCH;
}
info->flags &= ~FBINFO_MISC_MODESWITCH;
}
updatescrollmode(p, info, vc);
return 0;
......@@ -1771,6 +1766,13 @@ static int fbcon_switch(struct vc_data *vc)
}
fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
if (info->flags & FBINFO_MISC_MODESWITCH) {
if (info->fbops->fb_set_par)
info->fbops->fb_set_par(info);
info->flags &= ~FBINFO_MISC_MODESWITCH;
}
switch (p->scrollmode) {
case SCROLL_WRAP:
scrollback_phys_max = p->vrows - vc->vc_rows;
......@@ -1793,16 +1795,6 @@ static int fbcon_switch(struct vc_data *vc)
if (vt_cons[vc->vc_num]->vc_mode == KD_TEXT)
accel_clear_margins(vc, info, 0);
if (logo_shown == -2) {
struct fb_fillrect rect;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
rect.color = attr_bgcol_ec(bgshift, vc);
rect.rop = ROP_COPY;
rect.dx = rect.dy = 0;
rect.width = info->var.xres;
rect.height = logo_lines * vc->vc_font.height;
info->fbops->fb_fillrect(info, &rect);
logo_shown = fg_console;
/* This is protected above by initmem_freed */
fb_show_logo(info);
......
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