[Patch 4/9]: Amend internal manipulation of glyph structure

Alan Mackenzie <[email protected]>
Newsgroups gmane.linux.serial,gmane.linux.kernel,gmane.comp.video.dri.devel
Message-ID <[email protected]>
vt: 32b glyph: 4. Amend internal manipulation of glyph structure

This manipulation is the extraction/insertion of bit fields from/into the
16-bit/32-bit glyph.  It uses the new fields of struct vc_data,
vc_char_mask, vc_attr_mask, vc_attr_shift_pos in place of old hard coded
constants such as 0xff, 0xff00, 8.

Signed-off-by: Alan Mackenzie <[email protected]>

diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c
index 7d40eacc21b3..f23d61fe10c1 100644
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -272,6 +273,10 @@ static int vcs_read_buf_uni(struct vc_data *vc, char *con_buf,
 	return 0;
 }
 
+/*
+ * NOTE: This function returns the bottom 8 bits of the glyph for each pertinent
+ * screen character.  It is not very useful for a 9-bit or 21-bit glyph setup.
+ */
 static void vcs_read_buf_noattr(const struct vc_data *vc, char *con_buf,
 		unsigned int pos, unsigned int count, bool viewed)
 {
@@ -470,6 +499,10 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	return ret;
 }
 
+/*
+ * NOTE: This function writes the bottom 8-bits of the glyph code into the
+ * screen buffer.  It is not very useful for 9-bit or 21-bit glyphs.
+ */
 static u16 *vcs_write_buf_noattr(struct vc_data *vc, const char *con_buf,
 		unsigned int pos, unsigned int count, bool viewed, u16 **org0)
 {
@@ -497,25 +533,15 @@ static u16 *vcs_write_buf_noattr(struct vc_data *vc, const char *con_buf,
 	return org;
 }
 
-/*
- * Compilers (gcc 10) are unable to optimize the swap in cpu_to_le16. So do it
- * the poor man way.
- */
-static inline u16 vc_compile_le16(u8 hi, u8 lo)
-{
-#ifdef __BIG_ENDIAN
-	return (lo << 8u) | hi;
-#else
-	return (hi << 8u) | lo;
-#endif
-}
-
 static u16 *vcs_write_buf(struct vc_data *vc, const char *con_buf,
 		unsigned int pos, unsigned int count, bool viewed, u16 **org0)
 {
 	u16 *org;
 	unsigned int col, maxcol = vc->vc_cols;
 	unsigned char c;
+	unsigned int sz = GLYPH_SZ;
+	int i;
+	u8 lo_to_hi[4];
 
 	/* header */
 	if (pos < HEADER_SIZE) {
@@ -573,11 +619,27 @@ static u16 *vcs_write_buf(struct vc_data *vc, const char *con_buf,
 	if (!count)
 		return org;
 
-	/* odd pos -- the remaining character */
-	c = *con_buf++;
-	vcs_scr_writew(vc, vc_compile_le16(vcs_scr_readw(vc, org) >> 8, c),
-				org);
+	/* Unaligned bytes at end of buffer */
+	{
+		u32 old_char = vcs_scr_readw(vc, org);
+		u32 new_char = 0;
 
+		for (i = 0; i < sz; i++, old_char >>= 8)
+			lo_to_hi[i] = old_char & 0xff;
+		for (i = 0; i < count; i++) {
+			c = *con_buf++;
+#ifdef __BIG_ENDIAN
+			lo_to_hi[sz - i - 1] = c;
+#else
+			lo_to_hi[i] = c;
+#endif
+		}
+		for (i = sz - 1; i >= 0; i--) {
+			new_char <<= 8;
+			new_char |= lo_to_hi[i];
+		}
+		vcs_scr_writew(vc, new_char, org);
+	}
 	return org;
 }
 
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 8f467b22b799..0c389a564357 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -543,7 +544,7 @@ int vc_uniscr_check(struct vc_data *vc)
 	 * unicode content will be available after a complete screen refresh.
 	 */
 	p = (unsigned short *)vc->vc_origin;
-	mask = vc->vc_hi_font_mask | 0xff;
+	mask = vc->vc_char_mask;
 	for (y = 0; y < vc->vc_rows; y++) {
 		u32 *line = uni_lines[y];
 		for (x = 0; x < vc->vc_cols; x++) {
@@ -713,8 +719,6 @@ static u8 build_attr(struct vc_data *vc, u8 _color,
 		a ^= 0x80;
 	if (_intensity == VCI_BOLD)
 		a ^= 0x08;
-	if (vc->vc_hi_font_mask == 0x100)
-		a <<= 1;
 	return a;
 	}
 }
@@ -726,11 +730,11 @@ static void update_attr(struct vc_data *vc)
 	              vc->state.reverse ^ vc->vc_decscnm, vc->state.italic);
 	vc->vc_video_erase_char = ' ' | (build_attr(vc, vc->state.color,
 				VCI_NORMAL, vc->state.blink, false,
-				vc->vc_decscnm, false) << 8);
+				vc->vc_decscnm, false) << vc->vc_attr_shift_pos);
 }
 
-/* Note: inverting the screen twice should revert to the original state */
+/* Note: inverting the screen twice should revert to the original state.  */
 void invert_screen(struct vc_data *vc, int offset, int count, bool viewed)
 {
 	u16 *p;
 
@@ -742,34 +746,21 @@ void invert_screen(struct vc_data *vc, int offset, int count, bool viewed)
 		vc->vc_sw->con_invert_region(vc, p, count);
 	} else {
 		u16 *q = p;
 		int cnt = count;
-		u16 a;
-
-		if (!vc->vc_can_do_color) {
-			while (cnt--) {
-			    a = scr_readw(q);
-			    a ^= 0x0800;
-			    scr_writew(a, q);
-			    q++;
-			}
-		} else if (vc->vc_hi_font_mask == 0x100) {
-			while (cnt--) {
-				a = scr_readw(q);
-				a = (a & 0x11ff) |
-				   ((a & 0xe000) >> 4) |
-				   ((a & 0x0e00) << 4);
-				scr_writew(a, q);
-				q++;
-			}
-		} else {
-			while (cnt--) {
-				a = scr_readw(q);
-				a = (a & 0x88ff) |
-				   ((a & 0x7000) >> 4) |
-				   ((a & 0x0700) << 4);
-				scr_writew(a, q);
-				q++;
-			}
+		u32 a, c;
+
+		while (cnt--) {
+			c = scr_readg(q);
+			a = c >> vc->vc_attr_shift_pos;
+			if (!vc->vc_can_do_color)
+				a ^= 0x08;
+			else
+				a = (a & 0x88) |
+					((a & 0x70) >> 4) |
+					((a & 0x07) << 4);
+			c = (c & vc->vc_char_mask) |
+				(a << vc->vc_attr_shift_pos);
+			scr_writeg_plusplus(c, q++);
 		}
 	}
 
@@ -1041,19 +1037,37 @@ static void visual_init(struct vc_data *vc, int num, bool init)
 		con_free_unimap(vc);
 	vc->uni_pagedict_loc = &vc->uni_pagedict;
 	vc->uni_pagedict = NULL;
-	vc->vc_hi_font_mask = 0;
+	vc->vc_hi_font_mask = 0; /* Probably redundant, 2025-01-16. */
 	vc->vc_complement_mask = 0;
 	vc->vc_can_do_color = 0;
 	vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
+
 	vc->vc_sw->con_init(vc, init);
+	if (init) {
+#ifdef CONFIG_FB_GLYPH_21BIT
+		vc->vc_char_mask = 0x1fffff;
+		vc->vc_attr_mask = 0xff000000;
+		vc->vc_attr_shift_pos = 24;
+#else
+		if (vc->vc_font.charcount == 256) {
+			vc->vc_char_mask = 0xff;
+			vc->vc_attr_mask = 0xff00;
+			vc->vc_attr_shift_pos = 8;
+		} else {
+			vc->vc_char_mask = 0x1ff;
+			vc->vc_attr_mask = 0xfe00;
+			vc->vc_attr_shift_pos = 9;
+		}
+#endif
+	}
 	if (!vc->vc_complement_mask)
-		vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+		vc->vc_complement_mask = (vc->vc_can_do_color ? 0x77 : 0x08)
+			<< vc->vc_attr_shift_pos;
 	vc->vc_s_complement_mask = vc->vc_complement_mask;
-	vc->vc_size_row = vc->vc_cols << 1;
+	vc->vc_size_row = vc->vc_cols * GLYPH_SZ;
 	vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
 }
 
-
 static void visual_deinit(struct vc_data *vc)
 {
 	vc->vc_sw->con_deinit(vc);
@@ -1175,11 +1189,30 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
 	unsigned int new_cols, new_rows, new_row_size, new_screen_size;
 	unsigned short *oldscreen, *newscreen;
 	u32 **new_uniscr = NULL;
-
+	unsigned int new_vc_char_mask = vc->vc_char_mask;
+	unsigned int new_vc_attr_mask = vc->vc_attr_mask;
+	unsigned int new_vc_attr_shift_pos = vc->vc_attr_shift_pos;
+	unsigned int new_vc_video_erase_char = vc->vc_video_erase_char;
 	WARN_CONSOLE_UNLOCKED();
 
 	if (cols > VC_MAXCOL || lines > VC_MAXROW)
 		return -EINVAL;
 
+#ifndef CONFIG_FB_GLYPH_21BIT
+	if (vc->vc_hi_font_mask == 0x100) {
+		new_vc_char_mask = 0x1ff;
+		new_vc_attr_mask = 0xfe00;
+		new_vc_attr_shift_pos = 9;
+	} else {
+		new_vc_char_mask = 0xff;
+		new_vc_attr_mask = 0xff00;
+		new_vc_attr_shift_pos = 8;
+	}
+#endif
+	new_vc_video_erase_char =
+		(vc->vc_video_erase_char & vc->vc_char_mask) |
+		((vc->vc_video_erase_char >> vc->vc_attr_shift_pos) <<
+		 new_vc_attr_shift_pos);
+
 	new_cols = (cols ? cols : vc->vc_cols);
 	new_rows = (lines ? lines : vc->vc_rows);
@@ -2114,8 +2164,10 @@ static void csi_RSB(struct vc_data *vc)
 		break;
 	case CSI_RSB_MAKE_CUR_COLOR_DEFAULT:
 		vc->vc_def_color = vc->vc_attr;
+#ifndef CONFIG_FB_GLYPH_21BIT
 		if (vc->vc_hi_font_mask == 0x100)
 			vc->vc_def_color >>= 1;
+#endif
 		default_attr(vc);
 		update_attr(vc);
 		break;
@@ -2856,11 +2908,13 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, u8 c)
 		if (c == '8') {
 			/* DEC screen alignment test. kludge :-) */
 			vc->vc_video_erase_char =
-				(vc->vc_video_erase_char & 0xff00) | 'E';
+				(vc->vc_video_erase_char & vc->vc_attr_mask) | 'E';
 			csi_J(vc, CSI_J_VISIBLE);
 			vc->vc_video_erase_char =
-				(vc->vc_video_erase_char & 0xff00) | ' ';
-			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
+				(vc->vc_video_erase_char & vc->vc_attr_mask) | ' ';
+			do_update_region(vc, vc->vc_origin,
+					 vc->vc_screenbuf_size /
+					 GLYPH_SZ);
 		}
 		return;
 	case ESsetG0:	/* ESC ( */
@@ -3021,10 +3076,12 @@ static inline unsigned char vc_invert_attr(const struct vc_data *vc)
 	if (!vc->vc_can_do_color)
 		return vc->vc_attr ^ 0x08;
 
+#ifndef CONFIG_FB_GLYPH_21BIT
 	if (vc->vc_hi_font_mask == 0x100)
 		return   (vc->vc_attr & 0x11) |
 			((vc->vc_attr & 0xe0) >> 4) |
 			((vc->vc_attr & 0x0e) << 4);
+#endif
 
 	return   (vc->vc_attr & 0x88) |
 		((vc->vc_attr & 0x70) >> 4) |
@@ -3153,16 +3210,15 @@ static int vc_process_ucs(struct vc_data *vc, int *c, int *tc)
 static int vc_get_glyph(struct vc_data *vc, int tc)
 {
 	int glyph = conv_uni_to_pc(vc, tc);
-	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 
-	if (!(glyph & ~charmask))
+	if (!(glyph & ~vc->vc_char_mask))
 		return glyph;
 
 	if (glyph == -1)
 		return -1; /* nothing to display */
 
 	/* Glyph not found */
-	if ((!vc->vc_utf || vc->vc_disp_ctrl || tc < 128) && !(tc & ~charmask)) {
+	if ((!vc->vc_utf || vc->vc_disp_ctrl || tc < 128) && !(tc & ~vc->vc_char_mask)) {
 		/*
 		 * In legacy mode use the glyph we get by a 1:1 mapping.
 		 * This would make absolutely no sense with Unicode in mind, but do this for
diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
index 65681dcc5930..84e073162311 100644
--- a/drivers/video/fbdev/core/bitblit.c
+++ b/drivers/video/fbdev/core/bitblit.c
@@ -77,8 +77,8 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
 				     u32 d_pitch, u32 s_pitch, u32 cellsize,
 				     struct fb_image *image, u8 *buf, u8 *dst)
 {
-	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	unsigned int charcnt = vc->vc_font.charcount;
+	u32 charmask = vc->vc_char_mask;
 	u32 idx = vc->vc_font.width >> 3;
 	const u8 *src;
 
@@ -114,8 +113,8 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
 				       struct fb_image *image, u8 *buf,
 				       u8 *dst)
 {
-	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	unsigned int charcnt = vc->vc_font.charcount;
+	u32 charmask = vc->vc_char_mask;
 	u32 shift_low = 0, mod = vc->vc_font.width % 8;
 	u32 shift_high = 8;
 	u32 idx = vc->vc_font.width >> 3;
@@ -261,7 +260,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
 {
 	struct fb_cursor cursor;
 	struct fbcon_par *par = info->fbcon_par;
-	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+	unsigned int charmask = vc->vc_char_mask;
 	int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
 	int y = real_y(par->p, vc->state.y);
 	int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 9f5c4c101581..18fbf7cf11dd 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -319,14 +319,14 @@ static int get_color(struct vc_data *vc, struct fb_info *info,
 	int color = 0;
 
 	if (console_blanked) {
-		unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+		unsigned int charmask = vc->vc_char_mask;
 
 		c = vc->vc_video_erase_char & charmask;
 	}
 
 	if (depth != 1)
-		color = (is_fg) ? attr_fgcol((vc->vc_hi_font_mask) ? 9 : 8, c)
-			: attr_bgcol((vc->vc_hi_font_mask) ? 13 : 12, c);
+		color = (is_fg) ? ((c >> vc->vc_attr_shift_pos) & 0x0f)
+			: (c >> (vc->vc_attr_shift_pos + 4));
 
 	switch (depth) {
 	case 1:
@@ -1150,14 +1157,8 @@ static void fbcon_init(struct vc_data *vc, bool init)
 	}
 
 	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
-	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
-	if (vc->vc_font.charcount == 256) {
-		vc->vc_hi_font_mask = 0;
-	} else {
-		vc->vc_hi_font_mask = 0x100;
-		if (vc->vc_can_do_color)
-			vc->vc_complement_mask <<= 1;
-	}
+	vc->vc_complement_mask = (vc->vc_can_do_color ? 0x77 : 0x08) <<
+		(vc->vc_attr_shift_pos ? vc->vc_attr_shift_pos : 8);
 
 	if (!*svc->uni_pagedict_loc)
 		con_set_default_unimap(svc);
@@ -1242,7 +1244,9 @@ static void fbcon_free_font(struct fbcon_display *p)
 	}
 }
 
+#ifndef CONFIG_FB_GLYPH_21BIT
 static void set_vc_hi_font(struct vc_data *vc, bool set);
+#endif
 
 static void fbcon_release_all(void)
 {
@@ -1298,8 +1302,10 @@ static void fbcon_deinit(struct vc_data *vc)
 	fbcon_free_font(p);
 	vc->vc_font.data = NULL;
 
+#ifndef CONFIG_FB_GLYPH_21BIT
 	if (vc->vc_hi_font_mask && vc->vc_screenbuf)
 		set_vc_hi_font(vc, false);
+#endif
 
 	if (!con_is_bound(&fb_con))
 		fbcon_release_all();
@@ -1471,16 +1477,28 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
 	var->xoffset = info->var.xoffset;
 	fb_set_var(info, var);
 	par->var = info->var;
-	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
-	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+#ifdef CONFIG_FB_GLYPH_21BIT
+	vc->vc_hi_font_mask = 0;
+	vc->vc_char_mask = 0x1fffff;
+	vc->vc_attr_mask = 0xff000000;
+	vc->vc_attr_shift_pos = 24;
+#else
 	if (vc->vc_font.charcount == 256) {
 		vc->vc_hi_font_mask = 0;
+		vc->vc_char_mask = 0xff;
+		vc->vc_attr_mask = 0xff00;
+		vc->vc_attr_shift_pos = 8;
 	} else {
 		vc->vc_hi_font_mask = 0x100;
-		if (vc->vc_can_do_color)
-			vc->vc_complement_mask <<= 1;
+		vc->vc_char_mask = 0x1ff;
+		vc->vc_attr_mask = 0xfe00;
+		vc->vc_attr_shift_pos = 9;
 	}
+#endif
 
+	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix) != 1);
+	vc->vc_complement_mask = (vc->vc_can_do_color ? 0x77 : 0x08) <<
+		(vc->vc_attr_shift_pos ? vc->vc_attr_shift_pos : 8);
 	if (!*svc->uni_pagedict_loc)
 		con_set_default_unimap(svc);
 	if (!*vc->uni_pagedict_loc)
@@ -2220,10 +2258,8 @@ static bool fbcon_switch(struct vc_data *vc)
 	}
 
 	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
-	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
-
-	if (vc->vc_font.charcount > 256)
-		vc->vc_complement_mask <<= 1;
+	vc->vc_complement_mask = (vc->vc_can_do_color ? 0x77 : 0x08) <<
+		(vc->vc_attr_shift_pos ? vc->vc_attr_shift_pos : 8);
 
 	updatescrollmode(p, info, vc);
 
@@ -2270,9 +2306,8 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
 				int blank)
 {
 	if (blank) {
-		unsigned short charmask = vc->vc_hi_font_mask ?
-			0x1ff : 0xff;
-		unsigned short oldc;
+		unsigned int charmask = vc->vc_char_mask;
+		unsigned int oldc;
 
 		oldc = vc->vc_video_erase_char;
 		vc->vc_video_erase_char &= charmask;
@@ -2336,11 +2373,15 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch)
 	return font_data_export(p->fontdata, font, vpitch);
 }
 
+#ifndef CONFIG_FB_GLYPH_21BIT
 /* set/clear vc_hi_font_mask and update vc attrs accordingly */
 static void set_vc_hi_font(struct vc_data *vc, bool set)
 {
 	if (!set) {
 		vc->vc_hi_font_mask = 0;
+		vc->vc_attr_mask = 0xff00;
+		vc->vc_char_mask = 0xff;
+		vc->vc_attr_shift_pos = 8;
 		if (vc->vc_can_do_color) {
 			vc->vc_complement_mask >>= 1;
 			vc->vc_s_complement_mask >>= 1;
@@ -2406,7 +2452,9 @@ 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;
+#ifndef CONFIG_FB_GLYPH_21BIT
 	unsigned short old_hi_font_mask = vc->vc_hi_font_mask;
+#endif
 
 	font_data_get(data);
 
@@ -2453,11 +2504,13 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
 	vc->vc_font.height = old_height;
 	vc->vc_font.charcount = old_charcount;
 
+#ifndef CONFIG_FB_GLYPH_21BIT
 	/* 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);
+#endif
 
 	font_data_put(data);
 
@@ -2583,19 +2645,23 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
 
 /* As we might be inside of softback, we may work with non-contiguous buffer,
    that's why we have to use a separate routine. */
-static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
+static void fbcon_invert_region(struct vc_data *vc, u16 *p, int cnt)
 {
+	u32 attr;
+
 	while (cnt--) {
-		u16 a = scr_readw(p);
+		u32 a = scr_readg(p);
+
+		attr = a >> vc->vc_attr_shift_pos;
 		if (!vc->vc_can_do_color)
-			a ^= 0x0800;
-		else if (vc->vc_hi_font_mask == 0x100)
-			a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) |
-			    (((a) & 0x0e00) << 4);
+			attr ^= 0x08;
 		else
-			a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
-			    (((a) & 0x0700) << 4);
-		scr_writew(a, p++);
+			attr = (attr & 0x88) |
+				((attr & 0x70) >> 4) |
+				((attr & 0x07) << 4);
+		a = (a & vc->vc_char_mask) |
+			(attr << vc->vc_attr_shift_pos);
+		scr_writeg_plusplus(a, p++);
 	}
 }
 
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 407d207b14f1..5aaef363a343 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -105,12 +105,6 @@ struct fbcon_par {
      *  Attribute Decoding
      */
 
-/* Color */
-#define attr_fgcol(fgshift,s)    \
-	(((s) >> (fgshift)) & 0x0f)
-#define attr_bgcol(bgshift,s)    \
-	(((s) >> (bgshift)) & 0x0f)
-
 /* Monochrome */
 #define attr_bold(s) \
 	((s) & 0x200)
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index fe915afdece5..5afce52057ca 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -144,13 +153,16 @@ struct vc_data {
 	unsigned char	vc_halfcolor;		/* Color for half intensity mode */
 	/* cursor */
 	unsigned int	vc_cursor_type;
-	unsigned short	vc_complement_mask;	/* [#] Xor mask for mouse pointer */
-	unsigned short	vc_s_complement_mask;	/* Saved mouse pointer mask */
+	unsigned int	vc_complement_mask;	/* [#] Xor mask for mouse pointer */
+	unsigned int	vc_s_complement_mask;	/* Saved mouse pointer mask */
 	unsigned long	vc_pos;			/* Cursor address */
 	/* fonts */
 	unsigned short	vc_hi_font_mask;	/* [#] Attribute set for upper 256 chars of font or 0 if not supported */
-	struct vc_font vc_font;			/* Current VC font set */
-	unsigned short	vc_video_erase_char;	/* Background erase character */
+	unsigned int	vc_char_mask;		/* Character mask.  0x1fffff, 0x1ff, or 0xff. */
+	unsigned int	vc_attr_mask;		/* Attribute mask.  0xff000000, 0xfe00, 0xff00. */
+	unsigned int	vc_attr_shift_pos;	/* Position of 8-bit attributes: 24, 9, or 8. */
+	struct vc_font	vc_font;		/* Current VC font set */
+	unsigned int	vc_video_erase_char;	/* Background erase character */
 	/* VT terminal data */
 	unsigned int	vc_state;		/* Escape sequence parser state */
 	unsigned int	vc_npar,vc_par[NPAR];	/* Parameters of current escape sequence */
@@ -217,9 +229,18 @@ extern void vc_SAK(struct work_struct *work);
 #define CUR_SW				0x000010
 #define CUR_ALWAYS_BG			0x000020
 #define CUR_INVERT_FG_BG		0x000040
+
+#ifdef CONFIG_FB_GLYPH_21BIT
+#define CUR_FG (0x07 << vc->vc_attr_shift_pos)
+#define CUR_BG (0x70 << vc->vc_attr_shift_pos)
+#define CUR_TYPE_CHANGE			0x00ff00
+#define CUR_CHANGE(c) (((c) & CUR_TYPE_CHANGE) << (vc->vc_attr_shift_pos - 8))
+#else
 #define CUR_FG				0x000700
 #define CUR_BG				0x007000
 #define CUR_CHANGE(c)		 ((c) & 0x00ff00)
+#endif
+
 #define CUR_SET(c)		(((c) & 0xff0000) >> 8)
 
 bool con_is_visible(const struct vc_data *vc);


-- 
Alan Mackenzie (Nuremberg, Germany).
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.