aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/efifb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbdev/efifb.c')
-rw-r--r--drivers/video/fbdev/efifb.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index ff01bed7112f..3a010641f630 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -17,6 +17,7 @@
#include <asm/efi.h>
static bool request_mem_succeeded = false;
+static bool nowc = false;
static struct fb_var_screeninfo efifb_defined = {
.activate = FB_ACTIVATE_NOW,
@@ -99,6 +100,8 @@ static int efifb_setup(char *options)
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);
+ else if (!strcmp(this_opt, "nowc"))
+ nowc = true;
}
}
@@ -146,6 +149,10 @@ ATTRIBUTE_GROUPS(efifb);
static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */
+static struct pci_dev *efifb_pci_dev; /* dev with BAR covering the efifb */
+static struct resource *bar_resource;
+static u64 bar_offset;
+
static int efifb_probe(struct platform_device *dev)
{
struct fb_info *info;
@@ -200,6 +207,13 @@ static int efifb_probe(struct platform_device *dev)
efifb_fix.smem_start |= ext_lfb_base;
}
+ if (bar_resource &&
+ bar_resource->start + bar_offset != efifb_fix.smem_start) {
+ dev_info(&efifb_pci_dev->dev,
+ "BAR has moved, updating efifb address\n");
+ efifb_fix.smem_start = bar_resource->start + bar_offset;
+ }
+
efifb_defined.bits_per_pixel = screen_info.lfb_depth;
efifb_defined.xres = screen_info.lfb_width;
efifb_defined.yres = screen_info.lfb_height;
@@ -255,7 +269,10 @@ static int efifb_probe(struct platform_device *dev)
info->apertures->ranges[0].base = efifb_fix.smem_start;
info->apertures->ranges[0].size = size_remap;
- info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
+ if (nowc)
+ info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
+ else
+ info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
if (!info->screen_base) {
pr_err("efifb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
efifb_fix.smem_len, efifb_fix.smem_start);
@@ -364,15 +381,13 @@ static struct platform_driver efifb_driver = {
builtin_platform_driver(efifb_driver);
-#if defined(CONFIG_PCI) && !defined(CONFIG_X86)
-
-static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
+#if defined(CONFIG_PCI)
-static void claim_efifb_bar(struct pci_dev *dev, int idx)
+static void record_efifb_bar_resource(struct pci_dev *dev, int idx, u64 offset)
{
u16 word;
- pci_bar_found = true;
+ efifb_pci_dev = dev;
pci_read_config_word(dev, PCI_COMMAND, &word);
if (!(word & PCI_COMMAND_MEMORY)) {
@@ -383,12 +398,8 @@ static void claim_efifb_bar(struct pci_dev *dev, int idx)
return;
}
- if (pci_claim_resource(dev, idx)) {
- pci_dev_disabled = true;
- dev_err(&dev->dev,
- "BAR %d: failed to claim resource for efifb!\n", idx);
- return;
- }
+ bar_resource = &dev->resource[idx];
+ bar_offset = offset;
dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
}
@@ -399,7 +410,7 @@ static void efifb_fixup_resources(struct pci_dev *dev)
u64 size = screen_info.lfb_size;
int i;
- if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+ if (efifb_pci_dev || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
return;
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
@@ -415,7 +426,7 @@ static void efifb_fixup_resources(struct pci_dev *dev)
continue;
if (res->start <= base && res->end >= base + size - 1) {
- claim_efifb_bar(dev, i);
+ record_efifb_bar_resource(dev, i, base - res->start);
break;
}
}