]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fix VT mode change vs. fbcon
authorAndrew Morton <akpm@osdl.org>
Mon, 1 Mar 2004 15:04:41 +0000 (07:04 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 1 Mar 2004 15:04:41 +0000 (07:04 -0800)
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

This patch implements what we discussed earlier to fix the switch bewteen
KD_GRAPHICS and KD_TEXT.

It has been tested for a few days now and appear to resolve the problem for
affected users.

James: I know you have some objections, I don't fully agree with them, and
I want that in asap now, that bug has been plaguing fbdev since the very
beginning and it's time to get rid of that and my corresponding todolist
entry.  You are welcome to propose a patch on top of this one if you feel
you can make things cleaner.  The approach of adding a parameter to
con_blank() is Linus idea btw :)

I didn't add a separate function as that would have made the butchering of
drivers/char/vt beyond what I want to deal with in 2.6.

drivers/char/vt.c
drivers/char/vt_ioctl.c
drivers/video/console/fbcon.c
drivers/video/console/promcon.c
drivers/video/console/sticon.c
drivers/video/console/vgacon.c
drivers/video/fbmem.c
include/linux/console.h
include/linux/fb.h
include/linux/vt_kern.h

index 74075ac26aa2eea55ef111fafd4f6c6b0f722712..edc8c46fed6bf61289fdb610eb4039a281bcc650 100644 (file)
@@ -2743,12 +2743,12 @@ static void vesa_powerdown(void)
      *  Called only if powerdown features are allowed.
      */
     switch (vesa_blank_mode) {
-       case VESA_NO_BLANKING:
-           c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1);
+    case VESA_NO_BLANKING:
+           c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1, 0);
            break;
-       case VESA_VSYNC_SUSPEND:
-       case VESA_HSYNC_SUSPEND:
-           c->vc_sw->con_blank(c, VESA_POWERDOWN+1);
+    case VESA_VSYNC_SUSPEND:
+    case VESA_HSYNC_SUSPEND:
+           c->vc_sw->con_blank(c, VESA_POWERDOWN+1, 0);
            break;
     }
 }
@@ -2776,7 +2776,7 @@ void do_blank_screen(int entering_gfx)
        if (entering_gfx) {
                hide_cursor(currcons);
                save_screen(currcons);
-               sw->con_blank(vc_cons[currcons].d, -1);
+               sw->con_blank(vc_cons[currcons].d, -1, 1);
                console_blanked = fg_console + 1;
                set_origin(currcons);
                return;
@@ -2794,7 +2794,7 @@ void do_blank_screen(int entering_gfx)
 
        save_screen(currcons);
        /* In case we need to reset origin, blanking hook returns 1 */
-       i = sw->con_blank(vc_cons[currcons].d, 1);
+       i = sw->con_blank(vc_cons[currcons].d, 1, 0);
        console_blanked = fg_console + 1;
        if (i)
                set_origin(currcons);
@@ -2808,14 +2808,14 @@ void do_blank_screen(int entering_gfx)
        }
 
        if (vesa_blank_mode)
-               sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
+               sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1, 0);
 }
 
 
 /*
  * Called by timer as well as from vt_console_driver
  */
-void unblank_screen(void)
+void do_unblank_screen(int leaving_gfx)
 {
        int currcons;
 
@@ -2839,7 +2839,7 @@ void unblank_screen(void)
        }
 
        console_blanked = 0;
-       if (sw->con_blank(vc_cons[currcons].d, 0))
+       if (sw->con_blank(vc_cons[currcons].d, 0, leaving_gfx))
                /* Low-level driver cannot restore -> do it ourselves */
                update_screen(fg_console);
        if (console_blank_hook)
@@ -2848,6 +2848,17 @@ void unblank_screen(void)
        set_cursor(fg_console);
 }
 
+/*
+ * This is called by the outside world to cause a forced unblank, mostly for
+ * oopses. Currently, I just call do_unblank_screen(0), but we could eventually
+ * call it with 1 as an argument and so force a mode restore... that may kill
+ * X or at least garbage the screen but would also make the Oops visible...
+ */
+void unblank_screen(void)
+{
+       do_unblank_screen(0);
+}
+
 /*
  * We defer the timer blanking to work queue so it can take the console semaphore
  * (console operations can still happen at irq time, but only from printk which
index 510c613edb234b0f434f2ea0c070628b040e1351..d8c6acc8e62cfa1ce5dc75083d0f062dcbf256fe 100644 (file)
@@ -497,7 +497,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                 */
                acquire_console_sem();
                if (arg == KD_TEXT)
-                       unblank_screen();
+                       do_unblank_screen(1);
                else
                        do_blank_screen(1);
                release_console_sem();
@@ -1103,7 +1103,7 @@ void complete_change_console(unsigned int new_console)
        if (old_vc_mode != vt_cons[new_console]->vc_mode)
        {
                if (vt_cons[new_console]->vc_mode == KD_TEXT)
-                       unblank_screen();
+                       do_unblank_screen(1);
                else
                        do_blank_screen(1);
        }
@@ -1138,7 +1138,7 @@ void complete_change_console(unsigned int new_console)
                        if (old_vc_mode != vt_cons[new_console]->vc_mode)
                        {
                                if (vt_cons[new_console]->vc_mode == KD_TEXT)
-                                       unblank_screen();
+                                       do_unblank_screen(1);
                                else
                                        do_blank_screen(1);
                        }
index 54e932b8a836ed6e30c9ccf889b66e7f8c71acb4..09c06877ce1e68017f34bb45d47569aa616080ce 100644 (file)
@@ -159,7 +159,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
 static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
                        int height, int width);
 static int fbcon_switch(struct vc_data *vc);
-static int fbcon_blank(struct vc_data *vc, int blank);
+static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch);
 static int fbcon_font_op(struct vc_data *vc, struct console_font_op *op);
 static int fbcon_set_palette(struct vc_data *vc, unsigned char *table);
 static int fbcon_scrolldelta(struct vc_data *vc, int lines);
@@ -1697,14 +1697,23 @@ static int fbcon_switch(struct vc_data *vc)
        return 1;
 }
 
-static int fbcon_blank(struct vc_data *vc, int blank)
+static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
 {
        unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
        struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
        struct display *p = &fb_display[vc->vc_num];
 
-       if (blank < 0)          /* Entering graphics mode */
-               return 0;
+       if (mode_switch) {
+               struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+               struct fb_var_screeninfo var = info->var;
+
+               if (blank) {
+                       fbcon_cursor(vc, CM_ERASE);
+                       return 0;
+               }
+               var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+               fb_set_var(info, &var);
+       }
 
        fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
 
index b724842f23eeedcb10a8ae0f91eb96d8e4f01fd4..6c788c9140668f631668ce79d0d901a3d3eddb5e 100644 (file)
@@ -463,7 +463,7 @@ promcon_font_op(struct vc_data *conp, struct console_font_op *op)
 }
         
 static int
-promcon_blank(struct vc_data *conp, int blank)
+promcon_blank(struct vc_data *conp, int blank, int mode_switch)
 {
        if (blank) {
                promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
index 83aea4b8c11d7707a017286e5ee807ed9f2f58e5..9d7816b2077e7215b4edaf30b5d86b1a0ebfbdef 100644 (file)
@@ -250,26 +250,18 @@ static int sticon_set_origin(struct vc_data *conp)
     return 0;
 }
 
-static int sticon_blank(struct vc_data *c, int blank)
+static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
 {
-    switch (blank) {
-    case 0:            /* unblank */
-       vga_is_gfx = 0;
-       /* Tell console.c that it has to restore the screen itself */
-       return 1;
-    case 1:            /* normal blanking */
-    default:           /* VESA blanking */
-       if (vga_is_gfx)
-               return 0;
-       sticon_set_origin(c);
-       sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
-       return 1;
-    case -1:           /* Entering graphic mode */
-       sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
-       vga_is_gfx = 1;
+    if (blank == 0) {
+       if (mode_switch)
+           vga_is_gfx = 0;
        return 1;
     }
-    return 1;          /* console needs to restore screen itself */
+    sticon_set_origin(c);
+    sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
+    if (mode_switch)
+       vga_is_gfx = 1;
+    return 1;
 }
 
 static int sticon_scrolldelta(struct vc_data *conp, int lines)
index 2e0097307b0e8809966aa4b8f35d03542934b7f6..347e2fd33f0ecfd386a113a63fb7dc96e38166d1 100644 (file)
@@ -76,7 +76,7 @@ static void vgacon_init(struct vc_data *c, int init);
 static void vgacon_deinit(struct vc_data *c);
 static void vgacon_cursor(struct vc_data *c, int mode);
 static int vgacon_switch(struct vc_data *c);
-static int vgacon_blank(struct vc_data *c, int blank);
+static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
 static int vgacon_font_op(struct vc_data *c, struct console_font_op *op);
 static int vgacon_set_palette(struct vc_data *vc, unsigned char *table);
 static int vgacon_scrolldelta(struct vc_data *c, int lines);
@@ -661,7 +661,7 @@ static void vga_pal_blank(struct vgastate *state)
        }
 }
 
-static int vgacon_blank(struct vc_data *c, int blank)
+static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
 {
        switch (blank) {
        case 0:         /* Unblank */
@@ -678,7 +678,8 @@ static int vgacon_blank(struct vc_data *c, int blank)
                /* Tell console.c that it has to restore the screen itself */
                return 1;
        case 1:         /* Normal blanking */
-               if (vga_video_type == VIDEO_TYPE_VGAC) {
+       case -1:        /* Obsolete */
+               if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
                        vga_pal_blank(&state);
                        vga_palette_blanked = 1;
                        return 0;
@@ -686,11 +687,8 @@ static int vgacon_blank(struct vc_data *c, int blank)
                vgacon_set_origin(c);
                scr_memsetw((void *) vga_vram_base, BLANK,
                            c->vc_screenbuf_size);
-               return 1;
-       case -1:                /* Entering graphic mode */
-               scr_memsetw((void *) vga_vram_base, BLANK,
-                           c->vc_screenbuf_size);
-               vga_is_gfx = 1;
+               if (mode_switch)
+                       vga_is_gfx = 1;
                return 1;
        default:                /* VESA blanking */
                if (vga_video_type == VIDEO_TYPE_VGAC) {
index a8e4a2db6e69845bd768cbbe3e1af49308cf66d5..9a473e1e3d0eed5a2d061a65f92e188d6e1407a4 100644 (file)
@@ -955,7 +955,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 {
        int err;
 
-       if (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
+       if ((var->activate & FB_ACTIVATE_FORCE) ||
+           memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
                if (!info->fbops->fb_check_var) {
                        *var = info->var;
                        return 0;
index f6ff116ccfb37a8342a7e1cdbcab456daea1e09c..2092454b2d8fc456a128a34054c6996fa23d97df 100644 (file)
@@ -37,7 +37,7 @@ struct consw {
        int     (*con_scroll)(struct vc_data *, int, int, int, int);
        void    (*con_bmove)(struct vc_data *, int, int, int, int, int, int);
        int     (*con_switch)(struct vc_data *);
-       int     (*con_blank)(struct vc_data *, int);
+       int     (*con_blank)(struct vc_data *, int, int);
        int     (*con_font_op)(struct vc_data *, struct console_font_op *);
        int     (*con_resize)(struct vc_data *, unsigned int, unsigned int);
        int     (*con_set_palette)(struct vc_data *, unsigned char *);
index 91972971f387e0f5db1a561ed3260aa73252ee52..85176893dbf4eb715604a6c55a4a16bdabd9db62 100644 (file)
@@ -152,6 +152,7 @@ struct fb_bitfield {
 #define FB_ACTIVATE_VBL               16       /* activate values on next vbl  */
 #define FB_CHANGE_CMAP_VBL     32      /* change colormap on vbl       */
 #define FB_ACTIVATE_ALL               64       /* change all VCs on this fb    */
+#define FB_ACTIVATE_FORCE     128      /* force apply even when no change*/
 
 #define FB_ACCELF_TEXT         1       /* text mode acceleration */
 
index f5605e04656f15a01b356f26830a9ae847a1f5ea..d1f3c979ce14c9c2b65889a3266481b4e364cc66 100644 (file)
@@ -44,7 +44,8 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines);
 void vc_disallocate(unsigned int console);
 void reset_palette(int currcons);
 void set_palette(int currcons);
-void do_blank_screen(int gfx_mode);
+void do_blank_screen(int entering_gfx);
+void do_unblank_screen(int leaving_gfx);
 void unblank_screen(void);
 void poke_blanked_console(void);
 int con_font_op(int currcons, struct console_font_op *op);