efifb: Implement vga_default_device() (v2)
EFI doesn't typically make use of the legacy VGA ROM, but it may still be configured to pass that through to a given video device. This may lead to an inaccurate choice of default video device. Add support to efifb to pick out the correct active video device. v2: fix if->ifdef Signed-off-by: Matthew Garrett <mjg@redhat.com> Acked-by: hpa@zytor.com Cc: matt.fleming@intel.com Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
		
					parent
					
						
							
								88674088d1
							
						
					
				
			
			
				commit
				
					
						b4aa016305
					
				
			
		
					 2 changed files with 63 additions and 20 deletions
				
			
		|  | @ -17,4 +17,10 @@ | |||
| #define vga_readb(x) (*(x)) | ||||
| #define vga_writeb(x, y) (*(y) = (x)) | ||||
| 
 | ||||
| #ifdef CONFIG_FB_EFI | ||||
| #define __ARCH_HAS_VGA_DEFAULT_DEVICE | ||||
| extern struct pci_dev *vga_default_device(void); | ||||
| extern void vga_set_default_device(struct pci_dev *pdev); | ||||
| #endif | ||||
| 
 | ||||
| #endif /* _ASM_X86_VGA_H */ | ||||
|  |  | |||
|  | @ -18,6 +18,8 @@ | |||
| 
 | ||||
| static bool request_mem_succeeded = false; | ||||
| 
 | ||||
| static struct pci_dev *default_vga; | ||||
| 
 | ||||
| static struct fb_var_screeninfo efifb_defined __devinitdata = { | ||||
| 	.activate		= FB_ACTIVATE_NOW, | ||||
| 	.height			= -1, | ||||
|  | @ -298,35 +300,70 @@ static struct fb_ops efifb_ops = { | |||
| 	.fb_imageblit	= cfb_imageblit, | ||||
| }; | ||||
| 
 | ||||
| struct pci_dev *vga_default_device(void) | ||||
| { | ||||
| 	return default_vga; | ||||
| } | ||||
| 
 | ||||
| void vga_set_default_device(struct pci_dev *pdev) | ||||
| { | ||||
| 	default_vga = pdev; | ||||
| } | ||||
| 
 | ||||
| static int __init efifb_setup(char *options) | ||||
| { | ||||
| 	char *this_opt; | ||||
| 	int i; | ||||
| 	struct pci_dev *dev = NULL; | ||||
| 
 | ||||
| 	if (!options || !*options) | ||||
| 		return 0; | ||||
| 	if (options && *options) { | ||||
| 		while ((this_opt = strsep(&options, ",")) != NULL) { | ||||
| 			if (!*this_opt) continue; | ||||
| 
 | ||||
| 	while ((this_opt = strsep(&options, ",")) != NULL) { | ||||
| 		if (!*this_opt) continue; | ||||
| 
 | ||||
| 		for (i = 0; i < M_UNKNOWN; i++) { | ||||
| 			if (!strcmp(this_opt, dmi_list[i].optname) && | ||||
| 					dmi_list[i].base != 0) { | ||||
| 				screen_info.lfb_base = dmi_list[i].base; | ||||
| 				screen_info.lfb_linelength = dmi_list[i].stride; | ||||
| 				screen_info.lfb_width = dmi_list[i].width; | ||||
| 				screen_info.lfb_height = dmi_list[i].height; | ||||
| 			for (i = 0; i < M_UNKNOWN; i++) { | ||||
| 				if (!strcmp(this_opt, dmi_list[i].optname) && | ||||
| 				    dmi_list[i].base != 0) { | ||||
| 					screen_info.lfb_base = dmi_list[i].base; | ||||
| 					screen_info.lfb_linelength = dmi_list[i].stride; | ||||
| 					screen_info.lfb_width = dmi_list[i].width; | ||||
| 					screen_info.lfb_height = dmi_list[i].height; | ||||
| 				} | ||||
| 			} | ||||
| 			if (!strncmp(this_opt, "base:", 5)) | ||||
| 				screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0); | ||||
| 			else if (!strncmp(this_opt, "stride:", 7)) | ||||
| 				screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4; | ||||
| 			else if (!strncmp(this_opt, "height:", 7)) | ||||
| 				screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0); | ||||
| 			else if (!strncmp(this_opt, "width:", 6)) | ||||
| 				screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0); | ||||
| 		} | ||||
| 		if (!strncmp(this_opt, "base:", 5)) | ||||
| 			screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0); | ||||
| 		else if (!strncmp(this_opt, "stride:", 7)) | ||||
| 			screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4; | ||||
| 		else if (!strncmp(this_opt, "height:", 7)) | ||||
| 			screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0); | ||||
| 		else if (!strncmp(this_opt, "width:", 6)) | ||||
| 			screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	for_each_pci_dev(dev) { | ||||
| 		int i; | ||||
| 
 | ||||
| 		if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||||
| 			continue; | ||||
| 
 | ||||
| 		for (i=0; i < DEVICE_COUNT_RESOURCE; i++) { | ||||
| 			resource_size_t start, end; | ||||
| 
 | ||||
| 			if (!(pci_resource_flags(dev, i) & IORESOURCE_MEM)) | ||||
| 				continue; | ||||
| 
 | ||||
| 			start = pci_resource_start(dev, i); | ||||
| 			end  = pci_resource_end(dev, i); | ||||
| 
 | ||||
| 			if (!start || !end) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (screen_info.lfb_base >= start && | ||||
| 			    (screen_info.lfb_base + screen_info.lfb_size) < end) | ||||
| 				default_vga = dev; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Matthew Garrett
				Matthew Garrett