/* * Copyright 2008 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. * Copyright 2009 Jerome Glisse. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Dave Airlie * Alex Deucher * Jerome Glisse
*/
/* If you boot an IGP board with a discrete card as the primary, * the IGP rom is not accessible via the rom bar as the IGP rom is * part of the system bios. On boot, the system bios puts a * copy of the igp rom at the start of vram if a discrete card is * present.
*/ staticbool igp_read_bios_from_vram(struct radeon_device *rdev)
{
uint8_t __iomem *bios;
resource_size_t vram_base;
resource_size_t size = 256 * 1024; /* ??? */
if (!(rdev->flags & RADEON_IS_IGP)) if (!radeon_card_posted(rdev)) returnfalse;
rdev->bios = NULL; /* XXX: some cards may return 0 for rom size? ddx has a workaround */
bios = pci_map_rom(rdev->pdev, &size); if (!bios) { returnfalse;
}
#ifdef CONFIG_ACPI /* ATRM is used to get the BIOS on the discrete cards in * dual-gpu systems.
*/ /* retrieve the ROM in 4k blocks */ #define ATRM_BIOS_PAGE 4096 /** * radeon_atrm_call - fetch a chunk of the vbios * * @atrm_handle: acpi ATRM handle * @bios: vbios image pointer * @offset: offset of vbios image data to fetch * @len: length of vbios image data to fetch * * Executes ATRM to fetch a chunk of the discrete * vbios image on PX systems (all asics). * Returns the length of the buffer fetched.
*/ staticint radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, int offset, int len)
{
acpi_status status; union acpi_object atrm_arg_elements[2], *obj; struct acpi_object_list atrm_arg; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
staticbool radeon_atrm_get_bios(struct radeon_device *rdev)
{ int ret; int size = 256 * 1024; int i; struct pci_dev *pdev = NULL;
acpi_handle dhandle, atrm_handle;
acpi_status status; bool found = false;
/* ATRM is for the discrete card only */ if (rdev->flags & RADEON_IS_IGP) returnfalse;
while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) { if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) &&
(pdev->class != PCI_CLASS_DISPLAY_OTHER << 8)) continue;
dhandle = ACPI_HANDLE(&pdev->dev); if (!dhandle) continue;
status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); if (ACPI_SUCCESS(status)) {
found = true; break;
}
}
if (!found) returnfalse;
pci_dev_put(pdev);
rdev->bios = kmalloc(size, GFP_KERNEL); if (!rdev->bios) {
DRM_ERROR("Unable to allocate bios\n"); returnfalse;
}
for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
ret = radeon_atrm_call(atrm_handle,
rdev->bios,
(i * ATRM_BIOS_PAGE),
ATRM_BIOS_PAGE); if (ret < ATRM_BIOS_PAGE) break;
}
/* wait for SPLL_CHG_STATUS to change to 1 */
cg_spll_status = 0; while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
r = radeon_atrm_get_bios(rdev); if (!r)
r = radeon_acpi_vfct_bios(rdev); if (!r)
r = igp_read_bios_from_vram(rdev); if (!r)
r = radeon_read_bios(rdev); if (!r)
r = radeon_read_disabled_bios(rdev); if (!r)
r = radeon_read_platform_bios(rdev); if (!r || rdev->bios == NULL) {
DRM_ERROR("Unable to locate a BIOS ROM\n");
rdev->bios = NULL; returnfalse;
} if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]); goto free_bios;
}
tmp = RBIOS16(0x18); if (RBIOS8(tmp + 0x14) != 0x0) {
DRM_INFO("Not an x86 BIOS ROM, not using.\n"); goto free_bios;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.39Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.