diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-07-10 05:38:08 +0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-10-03 07:12:45 +0400 |
commit | cd42439da48529a3cd6f957b226fc627a64fb771 (patch) | |
tree | 8422a0d6f2d2b6ec4cca39acc6aede5ca6a8943c /drivers/gpu/drm/nouveau/nouveau_bios.c | |
parent | 70c0f263cc2eb12e02506eb75f0a71490e7dea4d (diff) | |
download | linux-cd42439da48529a3cd6f957b226fc627a64fb771.tar.xz |
drm/nouveau/oldbios: remove shadowing support, use bios subdev's image
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_bios.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 245 |
1 files changed, 1 insertions, 244 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 52c3992454ae..f86985363acf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -65,247 +65,6 @@ static bool nv_cksum(const uint8_t *data, unsigned int length) return false; } -static int -score_vbios(struct nvbios *bios, const bool writeable) -{ - if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) { - NV_TRACEWARN(bios->dev, "... BIOS signature not found\n"); - return 0; - } - - if (nv_cksum(bios->data, bios->data[2] * 512)) { - NV_TRACEWARN(bios->dev, "... BIOS checksum invalid\n"); - /* if a ro image is somewhat bad, it's probably all rubbish */ - return writeable ? 2 : 1; - } - - NV_TRACE(bios->dev, "... appears to be valid\n"); - return 3; -} - -static void -bios_shadow_prom(struct nvbios *bios) -{ - struct drm_device *dev = bios->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 pcireg, access; - u16 pcir; - int i; - - /* enable access to rom */ - if (dev_priv->card_type >= NV_50) - pcireg = 0x088050; - else - pcireg = NV_PBUS_PCI_NV_20; - access = nv_mask(dev, pcireg, 0x00000001, 0x00000000); - - /* bail if no rom signature, with a workaround for a PROM reading - * issue on some chipsets. the first read after a period of - * inactivity returns the wrong result, so retry the first header - * byte a few times before giving up as a workaround - */ - i = 16; - do { - if (nv_rd08(dev, NV_PROM_OFFSET + 0) == 0x55) - break; - } while (i--); - - if (!i || nv_rd08(dev, NV_PROM_OFFSET + 1) != 0xaa) - goto out; - - /* additional check (see note below) - read PCI record header */ - pcir = nv_rd08(dev, NV_PROM_OFFSET + 0x18) | - nv_rd08(dev, NV_PROM_OFFSET + 0x19) << 8; - if (nv_rd08(dev, NV_PROM_OFFSET + pcir + 0) != 'P' || - nv_rd08(dev, NV_PROM_OFFSET + pcir + 1) != 'C' || - nv_rd08(dev, NV_PROM_OFFSET + pcir + 2) != 'I' || - nv_rd08(dev, NV_PROM_OFFSET + pcir + 3) != 'R') - goto out; - - /* read entire bios image to system memory */ - bios->length = nv_rd08(dev, NV_PROM_OFFSET + 2) * 512; - bios->data = kmalloc(bios->length, GFP_KERNEL); - if (bios->data) { - for (i = 0; i < bios->length; i++) - bios->data[i] = nv_rd08(dev, NV_PROM_OFFSET + i); - } - -out: - /* disable access to rom */ - nv_wr32(dev, pcireg, access); -} - -static void -bios_shadow_pramin(struct nvbios *bios) -{ - struct drm_device *dev = bios->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 bar0 = 0; - int i; - - if (dev_priv->card_type >= NV_50) { - u64 addr = (u64)(nv_rd32(dev, 0x619f04) & 0xffffff00) << 8; - if (!addr) { - addr = (u64)nv_rd32(dev, 0x001700) << 16; - addr += 0xf0000; - } - - bar0 = nv_mask(dev, 0x001700, 0xffffffff, addr >> 16); - } - - /* bail if no rom signature */ - if (nv_rd08(dev, NV_PRAMIN_OFFSET + 0) != 0x55 || - nv_rd08(dev, NV_PRAMIN_OFFSET + 1) != 0xaa) - goto out; - - bios->length = nv_rd08(dev, NV_PRAMIN_OFFSET + 2) * 512; - bios->data = kmalloc(bios->length, GFP_KERNEL); - if (bios->data) { - for (i = 0; i < bios->length; i++) - bios->data[i] = nv_rd08(dev, NV_PRAMIN_OFFSET + i); - } - -out: - if (dev_priv->card_type >= NV_50) - nv_wr32(dev, 0x001700, bar0); -} - -static void -bios_shadow_pci(struct nvbios *bios) -{ - struct pci_dev *pdev = bios->dev->pdev; - size_t length; - - if (!pci_enable_rom(pdev)) { - void __iomem *rom = pci_map_rom(pdev, &length); - if (rom && length) { - bios->data = kmalloc(length, GFP_KERNEL); - if (bios->data) { - memcpy_fromio(bios->data, rom, length); - bios->length = length; - } - } - if (rom) - pci_unmap_rom(pdev, rom); - - pci_disable_rom(pdev); - } -} - -static void -bios_shadow_acpi(struct nvbios *bios) -{ - struct pci_dev *pdev = bios->dev->pdev; - int cnt = 65536 / ROM_BIOS_PAGE; - int ret; - - if (!nouveau_acpi_rom_supported(pdev)) - return; - - bios->data = kmalloc(cnt * ROM_BIOS_PAGE, GFP_KERNEL); - if (!bios->data) - return; - - bios->length = 0; - while (cnt--) { - ret = nouveau_acpi_get_bios_chunk(bios->data, bios->length, - ROM_BIOS_PAGE); - if (ret != ROM_BIOS_PAGE) - return; - - bios->length += ROM_BIOS_PAGE; - } -} - -struct methods { - const char desc[8]; - void (*shadow)(struct nvbios *); - const bool rw; - int score; - u32 size; - u8 *data; -}; - -static bool -bios_shadow(struct drm_device *dev) -{ - struct methods shadow_methods[] = { - { "PRAMIN", bios_shadow_pramin, true, 0, 0, NULL }, - { "PROM", bios_shadow_prom, false, 0, 0, NULL }, - { "ACPI", bios_shadow_acpi, true, 0, 0, NULL }, - { "PCIROM", bios_shadow_pci, true, 0, 0, NULL }, - {} - }; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - struct methods *mthd, *best; - const struct firmware *fw; - char fname[32]; - int ret; - - if (nouveau_vbios) { - /* try to match one of the built-in methods */ - mthd = shadow_methods; - do { - if (strcasecmp(nouveau_vbios, mthd->desc)) - continue; - NV_INFO(dev, "VBIOS source: %s\n", mthd->desc); - - mthd->shadow(bios); - mthd->score = score_vbios(bios, mthd->rw); - if (mthd->score) - return true; - } while ((++mthd)->shadow); - - /* attempt to load firmware image */ - snprintf(fname, sizeof(fname), "nouveau/%s", nouveau_vbios); - ret = request_firmware(&fw, fname, &dev->pdev->dev); - if (ret == 0) { - bios->length = fw->size; - bios->data = kmemdup(fw->data, fw->size, GFP_KERNEL); - release_firmware(fw); - - NV_INFO(dev, "VBIOS image: %s\n", nouveau_vbios); - if (score_vbios(bios, 1)) - return true; - - kfree(bios->data); - bios->data = NULL; - } - - NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios); - } - - mthd = shadow_methods; - do { - NV_TRACE(dev, "Checking %s for VBIOS\n", mthd->desc); - mthd->shadow(bios); - mthd->score = score_vbios(bios, mthd->rw); - mthd->size = bios->length; - mthd->data = bios->data; - bios->data = NULL; - } while (mthd->score != 3 && (++mthd)->shadow); - - mthd = shadow_methods; - best = mthd; - do { - if (mthd->score > best->score) { - kfree(best->data); - best = mthd; - } - } while ((++mthd)->shadow); - - if (best->score) { - NV_TRACE(dev, "Using VBIOS from %s\n", best->desc); - bios->length = best->size; - bios->data = best->data; - return true; - } - - NV_ERROR(dev, "No valid VBIOS image found\n"); - return false; -} - struct init_tbl_entry { char *name; uint8_t id; @@ -6400,7 +6159,7 @@ static bool NVInitVBIOS(struct drm_device *dev) spin_lock_init(&bios->lock); bios->dev = dev; - return bios_shadow(dev); + return _nv_bios(dev, &bios->data, &bios->length); } static int nouveau_parse_vbios_struct(struct drm_device *dev) @@ -6564,6 +6323,4 @@ nouveau_bios_takedown(struct drm_device *dev) nouveau_mxm_fini(dev); nouveau_i2c_fini(dev); - - kfree(dev_priv->vbios.data); } |