Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fbdev: vesafb: Detect VGA compatibility from screen info's VESA attributes

Test the vesa_attributes field in struct screen_info for compatibility
with VGA hardware. Vesafb currently tests bit 1 in screen_info's
capabilities field which indicates a 64-bit lfb address and is
unrelated to VGA compatibility.

Section 4.4 of the Vesa VBE 2.0 specifications defines that bit 5 in
the mode's attributes field signals VGA compatibility. The mode is
compatible with VGA hardware if the bit is clear. In that case, the
driver can access VGA state of the VBE's underlying hardware. The
vesafb driver uses this feature to program the color LUT in palette
modes. Without, colors might be incorrect.

The problem got introduced in commit 89ec4c238e7a ("[PATCH] vesafb: Fix
incorrect logo colors in x86_64"). It incorrectly stores the mode
attributes in the screen_info's capabilities field and updates vesafb
accordingly. Later, commit 5e8ddcbe8692 ("Video mode probing support for
the new x86 setup code") fixed the screen_info, but did not update vesafb.
Color output still tends to work, because bit 1 in capabilities is
usually 0.

Besides fixing the bug in vesafb, this commit introduces a helper that
reads the correct bit from screen_info.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 5e8ddcbe8692 ("Video mode probing support for the new x86 setup code")
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Cc: <stable@vger.kernel.org> # v2.6.23+
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

Thomas Zimmermann and committed by
Helge Deller
c2bc958b b03c3519

+11 -1
+1 -1
drivers/video/fbdev/vesafb.c
··· 271 271 if (si->orig_video_isVGA != VIDEO_TYPE_VLFB) 272 272 return -ENODEV; 273 273 274 - vga_compat = (si->capabilities & 2) ? 0 : 1; 274 + vga_compat = !__screen_info_vbe_mode_nonvga(si); 275 275 vesafb_fix.smem_start = si->lfb_base; 276 276 vesafb_defined.bits_per_pixel = si->lfb_depth; 277 277 if (15 == vesafb_defined.bits_per_pixel)
+10
include/linux/screen_info.h
··· 49 49 return lfb_size; 50 50 } 51 51 52 + static inline bool __screen_info_vbe_mode_nonvga(const struct screen_info *si) 53 + { 54 + /* 55 + * VESA modes typically run on VGA hardware. Set bit 5 signals that this 56 + * is not the case. Drivers can then not make use of VGA resources. See 57 + * Sec 4.4 of the VBE 2.0 spec. 58 + */ 59 + return si->vesa_attributes & BIT(5); 60 + } 61 + 52 62 static inline unsigned int __screen_info_video_type(unsigned int type) 53 63 { 54 64 switch (type) {