forked from mirrors/linux
		
	[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>
This commit is contained in:
		
							parent
							
								
									ac50ab3e45
								
							
						
					
					
						commit
						89ec4c238e
					
				
					 4 changed files with 33 additions and 7 deletions
				
			
		| 
						 | 
					@ -97,6 +97,7 @@
 | 
				
			||||||
#define PARAM_VESAPM_OFF	0x30
 | 
					#define PARAM_VESAPM_OFF	0x30
 | 
				
			||||||
#define PARAM_LFB_PAGES		0x32
 | 
					#define PARAM_LFB_PAGES		0x32
 | 
				
			||||||
#define PARAM_VESA_ATTRIB	0x34
 | 
					#define PARAM_VESA_ATTRIB	0x34
 | 
				
			||||||
 | 
					#define PARAM_CAPABILITIES	0x36
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 | 
					/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 | 
				
			||||||
#ifdef CONFIG_VIDEO_RETAIN
 | 
					#ifdef CONFIG_VIDEO_RETAIN
 | 
				
			||||||
| 
						 | 
					@ -233,6 +234,10 @@ mopar_gr:
 | 
				
			||||||
	movw	18(%di), %ax
 | 
						movw	18(%di), %ax
 | 
				
			||||||
	movl	%eax, %fs:(PARAM_LFB_SIZE)
 | 
						movl	%eax, %fs:(PARAM_LFB_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# store mode capabilities
 | 
				
			||||||
 | 
						movl 10(%di), %eax
 | 
				
			||||||
 | 
						movl %eax, %fs:(PARAM_CAPABILITIES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# switching the DAC to 8-bit is for <= 8 bpp only
 | 
					# switching the DAC to 8-bit is for <= 8 bpp only
 | 
				
			||||||
	movw	%fs:(PARAM_LFB_DEPTH), %ax
 | 
						movw	%fs:(PARAM_LFB_DEPTH), %ax
 | 
				
			||||||
	cmpw	$8, %ax
 | 
						cmpw	$8, %ax
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,6 +97,7 @@
 | 
				
			||||||
#define PARAM_VESAPM_OFF	0x30
 | 
					#define PARAM_VESAPM_OFF	0x30
 | 
				
			||||||
#define PARAM_LFB_PAGES		0x32
 | 
					#define PARAM_LFB_PAGES		0x32
 | 
				
			||||||
#define PARAM_VESA_ATTRIB	0x34
 | 
					#define PARAM_VESA_ATTRIB	0x34
 | 
				
			||||||
 | 
					#define PARAM_CAPABILITIES	0x36
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 | 
					/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 | 
				
			||||||
#ifdef CONFIG_VIDEO_RETAIN
 | 
					#ifdef CONFIG_VIDEO_RETAIN
 | 
				
			||||||
| 
						 | 
					@ -233,6 +234,10 @@ mopar_gr:
 | 
				
			||||||
	movw	18(%di), %ax
 | 
						movw	18(%di), %ax
 | 
				
			||||||
	movl	%eax, %fs:(PARAM_LFB_SIZE)
 | 
						movl	%eax, %fs:(PARAM_LFB_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# store mode capabilities
 | 
				
			||||||
 | 
						movl 10(%di), %eax
 | 
				
			||||||
 | 
						movl %eax, %fs:(PARAM_CAPABILITIES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# switching the DAC to 8-bit is for <= 8 bpp only
 | 
					# switching the DAC to 8-bit is for <= 8 bpp only
 | 
				
			||||||
	movw	%fs:(PARAM_LFB_DEPTH), %ax
 | 
						movw	%fs:(PARAM_LFB_DEPTH), %ax
 | 
				
			||||||
	cmpw	$8, %ax
 | 
						cmpw	$8, %ax
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ static unsigned short  *pmi_base  = NULL;
 | 
				
			||||||
static void            (*pmi_start)(void);
 | 
					static void            (*pmi_start)(void);
 | 
				
			||||||
static void            (*pmi_pal)(void);
 | 
					static void            (*pmi_pal)(void);
 | 
				
			||||||
static int             depth;
 | 
					static int             depth;
 | 
				
			||||||
 | 
					static int             vga_compat;
 | 
				
			||||||
/* --------------------------------------------------------------------- */
 | 
					/* --------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int vesafb_pan_display(struct fb_var_screeninfo *var,
 | 
					static int vesafb_pan_display(struct fb_var_screeninfo *var,
 | 
				
			||||||
| 
						 | 
					@ -83,9 +83,10 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
 | 
				
			||||||
static void vesa_setpalette(int regno, unsigned red, unsigned green,
 | 
					static void vesa_setpalette(int regno, unsigned red, unsigned green,
 | 
				
			||||||
			    unsigned blue)
 | 
								    unsigned blue)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int shift = 16 - depth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __i386__
 | 
					#ifdef __i386__
 | 
				
			||||||
	struct { u_char blue, green, red, pad; } entry;
 | 
						struct { u_char blue, green, red, pad; } entry;
 | 
				
			||||||
	int shift = 16 - depth;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pmi_setpal) {
 | 
						if (pmi_setpal) {
 | 
				
			||||||
		entry.red   = red   >> shift;
 | 
							entry.red   = red   >> shift;
 | 
				
			||||||
| 
						 | 
					@ -101,14 +102,20 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green,
 | 
				
			||||||
                  "d" (regno),          /* EDX */
 | 
					                  "d" (regno),          /* EDX */
 | 
				
			||||||
                  "D" (&entry),         /* EDI */
 | 
					                  "D" (&entry),         /* EDI */
 | 
				
			||||||
                  "S" (&pmi_pal));      /* ESI */
 | 
					                  "S" (&pmi_pal));      /* ESI */
 | 
				
			||||||
	} else {
 | 
							return;
 | 
				
			||||||
		/* without protected mode interface, try VGA registers... */
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * without protected mode interface and if VGA compatible,
 | 
				
			||||||
 | 
					 * try VGA registers...
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						if (vga_compat) {
 | 
				
			||||||
		outb_p(regno,       dac_reg);
 | 
							outb_p(regno,       dac_reg);
 | 
				
			||||||
		outb_p(red   >> shift, dac_val);
 | 
							outb_p(red   >> shift, dac_val);
 | 
				
			||||||
		outb_p(green >> shift, dac_val);
 | 
							outb_p(green >> shift, dac_val);
 | 
				
			||||||
		outb_p(blue  >> shift, dac_val);
 | 
							outb_p(blue  >> shift, dac_val);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 | 
					static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 | 
				
			||||||
| 
						 | 
					@ -214,6 +221,7 @@ static int __init vesafb_probe(struct platform_device *dev)
 | 
				
			||||||
	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
 | 
						if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
 | 
				
			||||||
	vesafb_fix.smem_start = screen_info.lfb_base;
 | 
						vesafb_fix.smem_start = screen_info.lfb_base;
 | 
				
			||||||
	vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
 | 
						vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
 | 
				
			||||||
	if (15 == vesafb_defined.bits_per_pixel)
 | 
						if (15 == vesafb_defined.bits_per_pixel)
 | 
				
			||||||
| 
						 | 
					@ -318,6 +326,12 @@ static int __init vesafb_probe(struct platform_device *dev)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) {
 | 
				
			||||||
 | 
							printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n"
 | 
				
			||||||
 | 
							                    "        colors may be incorrect\n");
 | 
				
			||||||
 | 
							vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vesafb_defined.xres_virtual = vesafb_defined.xres;
 | 
						vesafb_defined.xres_virtual = vesafb_defined.xres;
 | 
				
			||||||
	vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
 | 
						vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
 | 
				
			||||||
	if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
 | 
						if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
 | 
				
			||||||
| 
						 | 
					@ -354,7 +368,8 @@ static int __init vesafb_probe(struct platform_device *dev)
 | 
				
			||||||
	printk(KERN_INFO "vesafb: %s: "
 | 
						printk(KERN_INFO "vesafb: %s: "
 | 
				
			||||||
	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
 | 
						       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
 | 
				
			||||||
	       (vesafb_defined.bits_per_pixel > 8) ?
 | 
						       (vesafb_defined.bits_per_pixel > 8) ?
 | 
				
			||||||
	       "Truecolor" : "Pseudocolor",
 | 
						       "Truecolor" : (vga_compat || pmi_setpal) ?
 | 
				
			||||||
 | 
						       "Pseudocolor" : "Static Pseudocolor",
 | 
				
			||||||
	       screen_info.rsvd_size,
 | 
						       screen_info.rsvd_size,
 | 
				
			||||||
	       screen_info.red_size,
 | 
						       screen_info.red_size,
 | 
				
			||||||
	       screen_info.green_size,
 | 
						       screen_info.green_size,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,8 @@ struct screen_info {
 | 
				
			||||||
	u16 vesapm_off;		/* 0x30 */
 | 
						u16 vesapm_off;		/* 0x30 */
 | 
				
			||||||
	u16 pages;		/* 0x32 */
 | 
						u16 pages;		/* 0x32 */
 | 
				
			||||||
	u16 vesa_attributes;	/* 0x34 */
 | 
						u16 vesa_attributes;	/* 0x34 */
 | 
				
			||||||
				/* 0x36 -- 0x3f reserved for future expansion */
 | 
						u32 capabilities;       /* 0x36 */
 | 
				
			||||||
 | 
									/* 0x3a -- 0x3f reserved for future expansion */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct screen_info screen_info;
 | 
					extern struct screen_info screen_info;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue