aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2017-01-11 11:09:50 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-30 03:41:28 -0400
commit3fd37725c4e00858eaf2c31a1e3539df4e732772 (patch)
tree4f81af74fe29b3e2460798384cf86c81f029b15a
parentc75fe7899538890109aad7bbf92b2f304389e825 (diff)
fbcon: Fix vc attr at deinit
commit 8aac7f34369726d1a158788ae8aff3002d5eb528 upstream. fbcon can deal with vc_hi_font_mask (the upper 256 chars) and adjust the vc attrs dynamically when vc_hi_font_mask is changed at fbcon_init(). When the vc_hi_font_mask is set, it remaps the attrs in the existing console buffer with one bit shift up (for 9 bits), while it remaps with one bit shift down (for 8 bits) when the value is cleared. It works fine as long as the font gets updated after fbcon was initialized. However, we hit a bizarre problem when the console is switched to another fb driver (typically from vesafb or efifb to drmfb). At switching to the new fb driver, we temporarily rebind the console to the dummy console, then rebind to the new driver. During the switching, we leave the modified attrs as is. Thus, the new fbcon takes over the old buffer as if it were to contain 8 bits chars (although the attrs are still shifted for 9 bits), and effectively this results in the yellow color texts instead of the original white color, as found in the bugzilla entry below. An easy fix for this is to re-adjust the attrs before leaving the fbcon at con_deinit callback. Since the code to adjust the attrs is already present in the current fbcon code, in this patch, we simply factor out the relevant code, and call it from fbcon_deinit(). Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1000619 Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/video/console/fbcon.c67
1 files changed, 40 insertions, 27 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index b87f5cfdaea5..4db10d7990c9 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -1167,6 +1167,8 @@ static void fbcon_free_font(struct display *p, bool freefont)
1167 p->userfont = 0; 1167 p->userfont = 0;
1168} 1168}
1169 1169
1170static void set_vc_hi_font(struct vc_data *vc, bool set);
1171
1170static void fbcon_deinit(struct vc_data *vc) 1172static void fbcon_deinit(struct vc_data *vc)
1171{ 1173{
1172 struct display *p = &fb_display[vc->vc_num]; 1174 struct display *p = &fb_display[vc->vc_num];
@@ -1202,6 +1204,9 @@ finished:
1202 if (free_font) 1204 if (free_font)
1203 vc->vc_font.data = NULL; 1205 vc->vc_font.data = NULL;
1204 1206
1207 if (vc->vc_hi_font_mask)
1208 set_vc_hi_font(vc, false);
1209
1205 if (!con_is_bound(&fb_con)) 1210 if (!con_is_bound(&fb_con))
1206 fbcon_exit(); 1211 fbcon_exit();
1207 1212
@@ -2438,32 +2443,10 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
2438 return 0; 2443 return 0;
2439} 2444}
2440 2445
2441static int fbcon_do_set_font(struct vc_data *vc, int w, int h, 2446/* set/clear vc_hi_font_mask and update vc attrs accordingly */
2442 const u8 * data, int userfont) 2447static void set_vc_hi_font(struct vc_data *vc, bool set)
2443{ 2448{
2444 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 2449 if (!set) {
2445 struct fbcon_ops *ops = info->fbcon_par;
2446 struct display *p = &fb_display[vc->vc_num];
2447 int resize;
2448 int cnt;
2449 char *old_data = NULL;
2450
2451 if (con_is_visible(vc) && softback_lines)
2452 fbcon_set_origin(vc);
2453
2454 resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
2455 if (p->userfont)
2456 old_data = vc->vc_font.data;
2457 if (userfont)
2458 cnt = FNTCHARCNT(data);
2459 else
2460 cnt = 256;
2461 vc->vc_font.data = (void *)(p->fontdata = data);
2462 if ((p->userfont = userfont))
2463 REFCOUNT(data)++;
2464 vc->vc_font.width = w;
2465 vc->vc_font.height = h;
2466 if (vc->vc_hi_font_mask && cnt == 256) {
2467 vc->vc_hi_font_mask = 0; 2450 vc->vc_hi_font_mask = 0;
2468 if (vc->vc_can_do_color) { 2451 if (vc->vc_can_do_color) {
2469 vc->vc_complement_mask >>= 1; 2452 vc->vc_complement_mask >>= 1;
@@ -2486,7 +2469,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
2486 ((c & 0xfe00) >> 1) | (c & 0xff); 2469 ((c & 0xfe00) >> 1) | (c & 0xff);
2487 vc->vc_attr >>= 1; 2470 vc->vc_attr >>= 1;
2488 } 2471 }
2489 } else if (!vc->vc_hi_font_mask && cnt == 512) { 2472 } else {
2490 vc->vc_hi_font_mask = 0x100; 2473 vc->vc_hi_font_mask = 0x100;
2491 if (vc->vc_can_do_color) { 2474 if (vc->vc_can_do_color) {
2492 vc->vc_complement_mask <<= 1; 2475 vc->vc_complement_mask <<= 1;
@@ -2518,8 +2501,38 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
2518 } else 2501 } else
2519 vc->vc_video_erase_char = c & ~0x100; 2502 vc->vc_video_erase_char = c & ~0x100;
2520 } 2503 }
2521
2522 } 2504 }
2505}
2506
2507static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
2508 const u8 * data, int userfont)
2509{
2510 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
2511 struct fbcon_ops *ops = info->fbcon_par;
2512 struct display *p = &fb_display[vc->vc_num];
2513 int resize;
2514 int cnt;
2515 char *old_data = NULL;
2516
2517 if (con_is_visible(vc) && softback_lines)
2518 fbcon_set_origin(vc);
2519
2520 resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
2521 if (p->userfont)
2522 old_data = vc->vc_font.data;
2523 if (userfont)
2524 cnt = FNTCHARCNT(data);
2525 else
2526 cnt = 256;
2527 vc->vc_font.data = (void *)(p->fontdata = data);
2528 if ((p->userfont = userfont))
2529 REFCOUNT(data)++;
2530 vc->vc_font.width = w;
2531 vc->vc_font.height = h;
2532 if (vc->vc_hi_font_mask && cnt == 256)
2533 set_vc_hi_font(vc, false);
2534 else if (!vc->vc_hi_font_mask && cnt == 512)
2535 set_vc_hi_font(vc, true);
2523 2536
2524 if (resize) { 2537 if (resize) {
2525 int cols, rows; 2538 int cols, rows;