|
@@ -42,6 +42,7 @@
|
|
#include <linux/completion.h>
|
|
#include <linux/completion.h>
|
|
#include <linux/fb.h>
|
|
#include <linux/fb.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/pci.h>
|
|
|
|
+#include <linux/efi.h>
|
|
|
|
|
|
#include <linux/hyperv.h>
|
|
#include <linux/hyperv.h>
|
|
|
|
|
|
@@ -212,6 +213,7 @@ struct synthvid_msg {
|
|
|
|
|
|
struct hvfb_par {
|
|
struct hvfb_par {
|
|
struct fb_info *info;
|
|
struct fb_info *info;
|
|
|
|
+ struct resource mem;
|
|
bool fb_ready; /* fb device is ready */
|
|
bool fb_ready; /* fb device is ready */
|
|
struct completion wait;
|
|
struct completion wait;
|
|
u32 synthvid_version;
|
|
u32 synthvid_version;
|
|
@@ -460,13 +462,13 @@ static int synthvid_connect_vsp(struct hv_device *hdev)
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
|
|
- if (par->synthvid_version == SYNTHVID_VERSION_WIN7) {
|
|
|
|
|
|
+ if (par->synthvid_version == SYNTHVID_VERSION_WIN7)
|
|
screen_depth = SYNTHVID_DEPTH_WIN7;
|
|
screen_depth = SYNTHVID_DEPTH_WIN7;
|
|
- screen_fb_size = SYNTHVID_FB_SIZE_WIN7;
|
|
|
|
- } else {
|
|
|
|
|
|
+ else
|
|
screen_depth = SYNTHVID_DEPTH_WIN8;
|
|
screen_depth = SYNTHVID_DEPTH_WIN8;
|
|
- screen_fb_size = SYNTHVID_FB_SIZE_WIN8;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ screen_fb_size = hdev->channel->offermsg.offer.
|
|
|
|
+ mmio_megabytes * 1024 * 1024;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -627,26 +629,46 @@ static void hvfb_get_option(struct fb_info *info)
|
|
/* Get framebuffer memory from Hyper-V video pci space */
|
|
/* Get framebuffer memory from Hyper-V video pci space */
|
|
static int hvfb_getmem(struct fb_info *info)
|
|
static int hvfb_getmem(struct fb_info *info)
|
|
{
|
|
{
|
|
- struct pci_dev *pdev;
|
|
|
|
- ulong fb_phys;
|
|
|
|
|
|
+ struct hvfb_par *par = info->par;
|
|
|
|
+ struct pci_dev *pdev = NULL;
|
|
void __iomem *fb_virt;
|
|
void __iomem *fb_virt;
|
|
|
|
+ int gen2vm = efi_enabled(EFI_BOOT);
|
|
|
|
+ int ret;
|
|
|
|
|
|
- pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
|
|
|
|
|
|
+ par->mem.name = KBUILD_MODNAME;
|
|
|
|
+ par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
|
|
|
+ if (gen2vm) {
|
|
|
|
+ ret = allocate_resource(&hyperv_mmio, &par->mem,
|
|
|
|
+ screen_fb_size,
|
|
|
|
+ 0, -1,
|
|
|
|
+ screen_fb_size,
|
|
|
|
+ NULL, NULL);
|
|
|
|
+ if (ret != 0) {
|
|
|
|
+ pr_err("Unable to allocate framebuffer memory\n");
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
|
|
PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
|
|
PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
|
|
- if (!pdev) {
|
|
|
|
- pr_err("Unable to find PCI Hyper-V video\n");
|
|
|
|
- return -ENODEV;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!pdev) {
|
|
|
|
+ pr_err("Unable to find PCI Hyper-V video\n");
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
|
|
- if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
|
|
|
|
- pci_resource_len(pdev, 0) < screen_fb_size)
|
|
|
|
- goto err1;
|
|
|
|
|
|
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
|
|
|
|
+ pci_resource_len(pdev, 0) < screen_fb_size)
|
|
|
|
+ goto err1;
|
|
|
|
|
|
- fb_phys = pci_resource_end(pdev, 0) - screen_fb_size + 1;
|
|
|
|
- if (!request_mem_region(fb_phys, screen_fb_size, KBUILD_MODNAME))
|
|
|
|
- goto err1;
|
|
|
|
|
|
+ par->mem.end = pci_resource_end(pdev, 0);
|
|
|
|
+ par->mem.start = par->mem.end - screen_fb_size + 1;
|
|
|
|
+ ret = request_resource(&pdev->resource[0], &par->mem);
|
|
|
|
+ if (ret != 0) {
|
|
|
|
+ pr_err("Unable to request framebuffer memory\n");
|
|
|
|
+ goto err1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- fb_virt = ioremap(fb_phys, screen_fb_size);
|
|
|
|
|
|
+ fb_virt = ioremap(par->mem.start, screen_fb_size);
|
|
if (!fb_virt)
|
|
if (!fb_virt)
|
|
goto err2;
|
|
goto err2;
|
|
|
|
|
|
@@ -654,30 +676,42 @@ static int hvfb_getmem(struct fb_info *info)
|
|
if (!info->apertures)
|
|
if (!info->apertures)
|
|
goto err3;
|
|
goto err3;
|
|
|
|
|
|
- info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
|
|
|
|
- info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
|
|
|
|
- info->fix.smem_start = fb_phys;
|
|
|
|
|
|
+ if (gen2vm) {
|
|
|
|
+ info->apertures->ranges[0].base = screen_info.lfb_base;
|
|
|
|
+ info->apertures->ranges[0].size = screen_info.lfb_size;
|
|
|
|
+ } else {
|
|
|
|
+ info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
|
|
|
|
+ info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ info->fix.smem_start = par->mem.start;
|
|
info->fix.smem_len = screen_fb_size;
|
|
info->fix.smem_len = screen_fb_size;
|
|
info->screen_base = fb_virt;
|
|
info->screen_base = fb_virt;
|
|
info->screen_size = screen_fb_size;
|
|
info->screen_size = screen_fb_size;
|
|
|
|
|
|
- pci_dev_put(pdev);
|
|
|
|
|
|
+ if (!gen2vm)
|
|
|
|
+ pci_dev_put(pdev);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
err3:
|
|
err3:
|
|
iounmap(fb_virt);
|
|
iounmap(fb_virt);
|
|
err2:
|
|
err2:
|
|
- release_mem_region(fb_phys, screen_fb_size);
|
|
|
|
|
|
+ release_resource(&par->mem);
|
|
err1:
|
|
err1:
|
|
- pci_dev_put(pdev);
|
|
|
|
|
|
+ if (!gen2vm)
|
|
|
|
+ pci_dev_put(pdev);
|
|
|
|
+
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
|
|
/* Release the framebuffer */
|
|
/* Release the framebuffer */
|
|
static void hvfb_putmem(struct fb_info *info)
|
|
static void hvfb_putmem(struct fb_info *info)
|
|
{
|
|
{
|
|
|
|
+ struct hvfb_par *par = info->par;
|
|
|
|
+
|
|
iounmap(info->screen_base);
|
|
iounmap(info->screen_base);
|
|
- release_mem_region(info->fix.smem_start, screen_fb_size);
|
|
|
|
|
|
+ release_resource(&par->mem);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|