diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2006-04-11 01:55:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-11 09:18:54 -0400 |
commit | 89ec4c238e7a3d7e660291f3f1a8181381baad77 (patch) | |
tree | 8ba2ab49cea71cfff21ee7a56717f83746cb8d0c | |
parent | ac50ab3e45436900b5d73edd0c6b0744af560535 (diff) |
[PATCH] vesafb: Fix incorrect logo colors in x86_64
Bugzilla Bug 6299:
A pixel size of 8 bits produces wrong logo colors in x86_64.
The driver has 2 methods for setting the color map, using the protected
mode interface provided by the video BIOS and directly writing to the VGA
registers. The former is not supported in x86_64 and the latter is enabled
only in i386.
Fix by enabling the latter method in x86_64 only if supported by the BIOS.
If both methods are unsupported, change the visual of vesafb to
STATIC_PSEUDOCOLOR.
Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/i386/boot/video.S | 5 | ||||
-rw-r--r-- | arch/x86_64/boot/video.S | 5 | ||||
-rw-r--r-- | drivers/video/vesafb.c | 27 | ||||
-rw-r--r-- | include/linux/screen_info.h | 3 |
4 files changed, 33 insertions, 7 deletions
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S index 0000a2674537..c9343c3a8082 100644 --- a/arch/i386/boot/video.S +++ b/arch/i386/boot/video.S | |||
@@ -97,6 +97,7 @@ | |||
97 | #define PARAM_VESAPM_OFF 0x30 | 97 | #define PARAM_VESAPM_OFF 0x30 |
98 | #define PARAM_LFB_PAGES 0x32 | 98 | #define PARAM_LFB_PAGES 0x32 |
99 | #define PARAM_VESA_ATTRIB 0x34 | 99 | #define PARAM_VESA_ATTRIB 0x34 |
100 | #define PARAM_CAPABILITIES 0x36 | ||
100 | 101 | ||
101 | /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ | 102 | /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ |
102 | #ifdef CONFIG_VIDEO_RETAIN | 103 | #ifdef CONFIG_VIDEO_RETAIN |
@@ -233,6 +234,10 @@ mopar_gr: | |||
233 | movw 18(%di), %ax | 234 | movw 18(%di), %ax |
234 | movl %eax, %fs:(PARAM_LFB_SIZE) | 235 | movl %eax, %fs:(PARAM_LFB_SIZE) |
235 | 236 | ||
237 | # store mode capabilities | ||
238 | movl 10(%di), %eax | ||
239 | movl %eax, %fs:(PARAM_CAPABILITIES) | ||
240 | |||
236 | # switching the DAC to 8-bit is for <= 8 bpp only | 241 | # switching the DAC to 8-bit is for <= 8 bpp only |
237 | movw %fs:(PARAM_LFB_DEPTH), %ax | 242 | movw %fs:(PARAM_LFB_DEPTH), %ax |
238 | cmpw $8, %ax | 243 | cmpw $8, %ax |
diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S index 0587477c99f2..32327bb37aff 100644 --- a/arch/x86_64/boot/video.S +++ b/arch/x86_64/boot/video.S | |||
@@ -97,6 +97,7 @@ | |||
97 | #define PARAM_VESAPM_OFF 0x30 | 97 | #define PARAM_VESAPM_OFF 0x30 |
98 | #define PARAM_LFB_PAGES 0x32 | 98 | #define PARAM_LFB_PAGES 0x32 |
99 | #define PARAM_VESA_ATTRIB 0x34 | 99 | #define PARAM_VESA_ATTRIB 0x34 |
100 | #define PARAM_CAPABILITIES 0x36 | ||
100 | 101 | ||
101 | /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ | 102 | /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ |
102 | #ifdef CONFIG_VIDEO_RETAIN | 103 | #ifdef CONFIG_VIDEO_RETAIN |
@@ -233,6 +234,10 @@ mopar_gr: | |||
233 | movw 18(%di), %ax | 234 | movw 18(%di), %ax |
234 | movl %eax, %fs:(PARAM_LFB_SIZE) | 235 | movl %eax, %fs:(PARAM_LFB_SIZE) |
235 | 236 | ||
237 | # store mode capabilities | ||
238 | movl 10(%di), %eax | ||
239 | movl %eax, %fs:(PARAM_CAPABILITIES) | ||
240 | |||
236 | # switching the DAC to 8-bit is for <= 8 bpp only | 241 | # switching the DAC to 8-bit is for <= 8 bpp only |
237 | movw %fs:(PARAM_LFB_DEPTH), %ax | 242 | movw %fs:(PARAM_LFB_DEPTH), %ax |
238 | cmpw $8, %ax | 243 | cmpw $8, %ax |
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 8982e540214c..b0b9acfdd430 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -57,7 +57,7 @@ static unsigned short *pmi_base = NULL; | |||
57 | static void (*pmi_start)(void); | 57 | static void (*pmi_start)(void); |
58 | static void (*pmi_pal)(void); | 58 | static void (*pmi_pal)(void); |
59 | static int depth; | 59 | static int depth; |
60 | 60 | static int vga_compat; | |
61 | /* --------------------------------------------------------------------- */ | 61 | /* --------------------------------------------------------------------- */ |
62 | 62 | ||
63 | static int vesafb_pan_display(struct fb_var_screeninfo *var, | 63 | static int vesafb_pan_display(struct fb_var_screeninfo *var, |
@@ -83,9 +83,10 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, | |||
83 | static void vesa_setpalette(int regno, unsigned red, unsigned green, | 83 | static void vesa_setpalette(int regno, unsigned red, unsigned green, |
84 | unsigned blue) | 84 | unsigned blue) |
85 | { | 85 | { |
86 | int shift = 16 - depth; | ||
87 | |||
86 | #ifdef __i386__ | 88 | #ifdef __i386__ |
87 | struct { u_char blue, green, red, pad; } entry; | 89 | struct { u_char blue, green, red, pad; } entry; |
88 | int shift = 16 - depth; | ||
89 | 90 | ||
90 | if (pmi_setpal) { | 91 | if (pmi_setpal) { |
91 | entry.red = red >> shift; | 92 | entry.red = red >> shift; |
@@ -101,14 +102,20 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green, | |||
101 | "d" (regno), /* EDX */ | 102 | "d" (regno), /* EDX */ |
102 | "D" (&entry), /* EDI */ | 103 | "D" (&entry), /* EDI */ |
103 | "S" (&pmi_pal)); /* ESI */ | 104 | "S" (&pmi_pal)); /* ESI */ |
104 | } else { | 105 | return; |
105 | /* without protected mode interface, try VGA registers... */ | 106 | } |
107 | #endif | ||
108 | |||
109 | /* | ||
110 | * without protected mode interface and if VGA compatible, | ||
111 | * try VGA registers... | ||
112 | */ | ||
113 | if (vga_compat) { | ||
106 | outb_p(regno, dac_reg); | 114 | outb_p(regno, dac_reg); |
107 | outb_p(red >> shift, dac_val); | 115 | outb_p(red >> shift, dac_val); |
108 | outb_p(green >> shift, dac_val); | 116 | outb_p(green >> shift, dac_val); |
109 | outb_p(blue >> shift, dac_val); | 117 | outb_p(blue >> shift, dac_val); |
110 | } | 118 | } |
111 | #endif | ||
112 | } | 119 | } |
113 | 120 | ||
114 | static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, | 121 | static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, |
@@ -214,6 +221,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
214 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) | 221 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) |
215 | return -ENODEV; | 222 | return -ENODEV; |
216 | 223 | ||
224 | vga_compat = (screen_info.capabilities & 2) ? 0 : 1; | ||
217 | vesafb_fix.smem_start = screen_info.lfb_base; | 225 | vesafb_fix.smem_start = screen_info.lfb_base; |
218 | vesafb_defined.bits_per_pixel = screen_info.lfb_depth; | 226 | vesafb_defined.bits_per_pixel = screen_info.lfb_depth; |
219 | if (15 == vesafb_defined.bits_per_pixel) | 227 | if (15 == vesafb_defined.bits_per_pixel) |
@@ -318,6 +326,12 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
318 | } | 326 | } |
319 | } | 327 | } |
320 | 328 | ||
329 | if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) { | ||
330 | printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n" | ||
331 | " colors may be incorrect\n"); | ||
332 | vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; | ||
333 | } | ||
334 | |||
321 | vesafb_defined.xres_virtual = vesafb_defined.xres; | 335 | vesafb_defined.xres_virtual = vesafb_defined.xres; |
322 | vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length; | 336 | vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length; |
323 | if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) { | 337 | if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) { |
@@ -354,7 +368,8 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
354 | printk(KERN_INFO "vesafb: %s: " | 368 | printk(KERN_INFO "vesafb: %s: " |
355 | "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", | 369 | "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", |
356 | (vesafb_defined.bits_per_pixel > 8) ? | 370 | (vesafb_defined.bits_per_pixel > 8) ? |
357 | "Truecolor" : "Pseudocolor", | 371 | "Truecolor" : (vga_compat || pmi_setpal) ? |
372 | "Pseudocolor" : "Static Pseudocolor", | ||
358 | screen_info.rsvd_size, | 373 | screen_info.rsvd_size, |
359 | screen_info.red_size, | 374 | screen_info.red_size, |
360 | screen_info.green_size, | 375 | screen_info.green_size, |
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h index 6336987dae62..2925e66a6732 100644 --- a/include/linux/screen_info.h +++ b/include/linux/screen_info.h | |||
@@ -41,7 +41,8 @@ struct screen_info { | |||
41 | u16 vesapm_off; /* 0x30 */ | 41 | u16 vesapm_off; /* 0x30 */ |
42 | u16 pages; /* 0x32 */ | 42 | u16 pages; /* 0x32 */ |
43 | u16 vesa_attributes; /* 0x34 */ | 43 | u16 vesa_attributes; /* 0x34 */ |
44 | /* 0x36 -- 0x3f reserved for future expansion */ | 44 | u32 capabilities; /* 0x36 */ |
45 | /* 0x3a -- 0x3f reserved for future expansion */ | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | extern struct screen_info screen_info; | 48 | extern struct screen_info screen_info; |