efifb: Implement vga_default_device() (v2)
authorMatthew Garrett <mjg@redhat.com>
Mon, 16 Apr 2012 20:26:05 +0000 (16:26 -0400)
committerDave Airlie <airlied@redhat.com>
Tue, 24 Apr 2012 08:50:18 +0000 (09:50 +0100)
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>
arch/x86/include/asm/vga.h
drivers/video/efifb.c

index c4b9dc2f67c5f6f7a095dd7d4a3a6bb7fd7b3975..44282fbf7bf95c9e36c1ce200810d2a7c6163bf2 100644 (file)
 #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 */
index 784139aed0793cab282cf52f3f3c3503a85a9a5a..66ed991ed8ba9e69a74f232d1b95299f577f73a8 100644 (file)
@@ -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) {
+               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;
+                               }
+                       }
+                       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 (!options || !*options)
-               return 0;
+       for_each_pci_dev(dev) {
+               int i;
 
-       while ((this_opt = strsep(&options, ",")) != NULL) {
-               if (!*this_opt) continue;
+               if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+                       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 < 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;
                }
-               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);
        }
+
        return 0;
 }