aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-01-23 23:14:19 -0500
committerDave Airlie <airlied@redhat.com>2013-02-06 21:37:03 -0500
commit2a2483072393b27f4336ab068a1f48ca19ff1c1e (patch)
tree388d0b8d5f208db9dabcca235a4da79a8bafd1ff
parent1589a3e7777631ff56dd58cd7dcdf275185e62b5 (diff)
vgacon/vt: clear buffer attributes when we load a 512 character font (v2)
When we switch from 256->512 byte font rendering mode, it means the current contents of the screen is being reinterpreted. The bit that holds the high bit of the 9-bit font, may have been previously set, and thus the new font misrenders. The problem case we see is grub2 writes spaces with the bit set, so it ends up with data like 0x820, which gets reinterpreted into 0x120 char which the font translates into G with a circumflex. This flashes up on screen at boot and is quite ugly. A current side effect of this patch though is that any rendering on the screen changes color to a slightly darker color, but at least the screen no longer corrupts. v2: as suggested by hpa, always clear the attribute space, whether we are are going to or from 512 chars. Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/tty/vt/vt.c2
-rw-r--r--drivers/video/console/vgacon.c22
-rw-r--r--include/linux/vt_kern.h1
3 files changed, 17 insertions, 8 deletions
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 8fd89687d068..c8067aef4b86 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -638,7 +638,7 @@ static inline void save_screen(struct vc_data *vc)
638 * Redrawing of screen 638 * Redrawing of screen
639 */ 639 */
640 640
641static void clear_buffer_attributes(struct vc_data *vc) 641void clear_buffer_attributes(struct vc_data *vc)
642{ 642{
643 unsigned short *p = (unsigned short *)vc->vc_origin; 643 unsigned short *p = (unsigned short *)vc->vc_origin;
644 int count = vc->vc_screenbuf_size / 2; 644 int count = vc->vc_screenbuf_size / 2;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d449a74d4a31..5855d17d19ac 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1064,7 +1064,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
1064 unsigned short video_port_status = vga_video_port_reg + 6; 1064 unsigned short video_port_status = vga_video_port_reg + 6;
1065 int font_select = 0x00, beg, i; 1065 int font_select = 0x00, beg, i;
1066 char *charmap; 1066 char *charmap;
1067 1067 bool clear_attribs = false;
1068 if (vga_video_type != VIDEO_TYPE_EGAM) { 1068 if (vga_video_type != VIDEO_TYPE_EGAM) {
1069 charmap = (char *) VGA_MAP_MEM(colourmap, 0); 1069 charmap = (char *) VGA_MAP_MEM(colourmap, 0);
1070 beg = 0x0e; 1070 beg = 0x0e;
@@ -1169,12 +1169,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
1169 1169
1170 /* if 512 char mode is already enabled don't re-enable it. */ 1170 /* if 512 char mode is already enabled don't re-enable it. */
1171 if ((set) && (ch512 != vga_512_chars)) { 1171 if ((set) && (ch512 != vga_512_chars)) {
1172 /* attribute controller */
1173 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1174 struct vc_data *c = vc_cons[i].d;
1175 if (c && c->vc_sw == &vga_con)
1176 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1177 }
1178 vga_512_chars = ch512; 1172 vga_512_chars = ch512;
1179 /* 256-char: enable intensity bit 1173 /* 256-char: enable intensity bit
1180 512-char: disable intensity bit */ 1174 512-char: disable intensity bit */
@@ -1185,8 +1179,22 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
1185 it means, but it works, and it appears necessary */ 1179 it means, but it works, and it appears necessary */
1186 inb_p(video_port_status); 1180 inb_p(video_port_status);
1187 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); 1181 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
1182 clear_attribs = true;
1188 } 1183 }
1189 raw_spin_unlock_irq(&vga_lock); 1184 raw_spin_unlock_irq(&vga_lock);
1185
1186 if (clear_attribs) {
1187 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1188 struct vc_data *c = vc_cons[i].d;
1189 if (c && c->vc_sw == &vga_con) {
1190 /* force hi font mask to 0, so we always clear
1191 the bit on either transition */
1192 c->vc_hi_font_mask = 0x00;
1193 clear_buffer_attributes(c);
1194 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1195 }
1196 }
1197 }
1190 return 0; 1198 return 0;
1191} 1199}
1192 1200
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 50ae7d0c279e..1f55665d7b49 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -47,6 +47,7 @@ int con_set_cmap(unsigned char __user *cmap);
47int con_get_cmap(unsigned char __user *cmap); 47int con_get_cmap(unsigned char __user *cmap);
48void scrollback(struct vc_data *vc, int lines); 48void scrollback(struct vc_data *vc, int lines);
49void scrollfront(struct vc_data *vc, int lines); 49void scrollfront(struct vc_data *vc, int lines);
50void clear_buffer_attributes(struct vc_data *vc);
50void update_region(struct vc_data *vc, unsigned long start, int count); 51void update_region(struct vc_data *vc, unsigned long start, int count);
51void redraw_screen(struct vc_data *vc, int is_switch); 52void redraw_screen(struct vc_data *vc, int is_switch);
52#define update_screen(x) redraw_screen(x, 0) 53#define update_screen(x) redraw_screen(x, 0)