Skip to content

Commit

Permalink
efifb: Implement vga_default_device() (v2)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Matthew Garrett authored and Dave Airlie committed Apr 24, 2012
1 parent 8867408 commit b4aa016
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 20 deletions.
6 changes: 6 additions & 0 deletions arch/x86/include/asm/vga.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
77 changes: 57 additions & 20 deletions drivers/video/efifb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit b4aa016

Please sign in to comment.