|
@@ -149,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;
|
|
@@ -203,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;
|
|
@@ -370,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)) {
|
|
@@ -389,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);
|
|
|
}
|
|
@@ -405,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)
|
|
@@ -421,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;
|
|
|
}
|
|
|
}
|