aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2006-04-11 01:55:48 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:54 -0400
commit89ec4c238e7a3d7e660291f3f1a8181381baad77 (patch)
tree8ba2ab49cea71cfff21ee7a56717f83746cb8d0c
parentac50ab3e45436900b5d73edd0c6b0744af560535 (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.S5
-rw-r--r--arch/x86_64/boot/video.S5
-rw-r--r--drivers/video/vesafb.c27
-rw-r--r--include/linux/screen_info.h3
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;
57static void (*pmi_start)(void); 57static void (*pmi_start)(void);
58static void (*pmi_pal)(void); 58static void (*pmi_pal)(void);
59static int depth; 59static int depth;
60 60static int vga_compat;
61/* --------------------------------------------------------------------- */ 61/* --------------------------------------------------------------------- */
62 62
63static int vesafb_pan_display(struct fb_var_screeninfo *var, 63static int vesafb_pan_display(struct fb_var_screeninfo *var,
@@ -83,9 +83,10 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
83static void vesa_setpalette(int regno, unsigned red, unsigned green, 83static 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
114static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, 121static 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
47extern struct screen_info screen_info; 48extern struct screen_info screen_info;