diff options
Diffstat (limited to 'drivers/video/fbdev/core')
| -rw-r--r-- | drivers/video/fbdev/core/fbcon.c | 14 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbmem.c | 12 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbsysfs.c | 10 |
3 files changed, 32 insertions, 4 deletions
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 9077d3b99357..9f5c4c101581 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1273,6 +1273,7 @@ static void fbcon_deinit(struct vc_data *vc) int idx; fbcon_free_font(p); + p->mode = NULL; idx = con2fb_map[vc->vc_num]; if (idx == -1) @@ -1443,14 +1444,14 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, p = &fb_display[unit]; - if (var_to_display(p, var, info)) - return; - vc = vc_cons[unit].d; if (!vc) return; + if (var_to_display(p, var, info)) + return; + default_mode = vc->vc_display_fg; svc = *default_mode; t = &fb_display[svc->vc_num]; @@ -2405,6 +2406,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount, int resize, ret, old_width, old_height, old_charcount; font_data_t *old_fontdata = p->fontdata; const u8 *old_data = vc->vc_font.data; + unsigned short old_hi_font_mask = vc->vc_hi_font_mask; font_data_get(data); @@ -2451,6 +2453,12 @@ err_out: vc->vc_font.height = old_height; vc->vc_font.charcount = old_charcount; + /* Restore the hi_font state and screen buffer */ + if (old_hi_font_mask && !vc->vc_hi_font_mask) + set_vc_hi_font(vc, true); + else if (!old_hi_font_mask && vc->vc_hi_font_mask) + set_vc_hi_font(vc, false); + font_data_put(data); return ret; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index e5221653ec2b..2f1c56e5a7a2 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -767,6 +767,18 @@ int fb_new_modelist(struct fb_info *info) if (list_empty(&info->modelist)) return 1; + /* + * The new modelist may not contain the current mode (info->var), and + * fbcon_new_modelist() below only re-points consoles mapped to this + * framebuffer. Add the current mode here so info->var keeps a match + * even when fbcon is unbound. + */ + if (!fb_match_mode(&info->var, &info->modelist)) { + fb_var_to_videomode(&mode, &info->var); + if (fb_add_videomode(&mode, &info->modelist)) + return 1; + } + fbcon_new_modelist(info); return 0; diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c index d9743ef35355..ea196603c7a8 100644 --- a/drivers/video/fbdev/core/fbsysfs.c +++ b/drivers/video/fbdev/core/fbsysfs.c @@ -10,6 +10,7 @@ #include <linux/major.h> #include "fb_internal.h" +#include "fbcon.h" static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var) { @@ -108,8 +109,15 @@ static ssize_t store_modes(struct device *device, if (fb_new_modelist(fb_info)) { fb_destroy_modelist(&fb_info->modelist); list_splice(&old_list, &fb_info->modelist); - } else + } else { + /* + * fb_display[i].mode and fb_info->mode both point into the old + * list. Clear them before it is freed. + */ + fbcon_delete_modelist(&old_list); + fb_info->mode = NULL; fb_destroy_modelist(&old_list); + } unlock_fb_info(fb_info); console_unlock(); |
