radeon_bios.c revision 255572
189857Sobrien/* 289857Sobrien * Copyright 2008 Advanced Micro Devices, Inc. 3218822Sdim * Copyright 2008 Red Hat Inc. 4218822Sdim * Copyright 2009 Jerome Glisse. 5218822Sdim * 6218822Sdim * Permission is hereby granted, free of charge, to any person obtaining a 789857Sobrien * copy of this software and associated documentation files (the "Software"), 889857Sobrien * to deal in the Software without restriction, including without limitation 989857Sobrien * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1089857Sobrien * and/or sell copies of the Software, and to permit persons to whom the 1189857Sobrien * Software is furnished to do so, subject to the following conditions: 1289857Sobrien * 1389857Sobrien * The above copyright notice and this permission notice shall be included in 1489857Sobrien * all copies or substantial portions of the Software. 1589857Sobrien * 1689857Sobrien * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1789857Sobrien * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1889857Sobrien * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1989857Sobrien * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2089857Sobrien * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2189857Sobrien * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22218822Sdim * OTHER DEALINGS IN THE SOFTWARE. 23218822Sdim * 2489857Sobrien * Authors: Dave Airlie 2589857Sobrien * Alex Deucher 2689857Sobrien * Jerome Glisse 2789857Sobrien */ 2889857Sobrien 2989857Sobrien#include <sys/cdefs.h> 3089857Sobrien__FBSDID("$FreeBSD: head/sys/dev/drm2/radeon/radeon_bios.c 255572 2013-09-14 17:22:34Z dumbbell $"); 3189857Sobrien 3289857Sobrien#include <dev/drm2/drmP.h> 3389857Sobrien#include "radeon_reg.h" 3489857Sobrien#include "radeon.h" 3589857Sobrien#include "atom.h" 3689857Sobrien 3789857Sobrien/* 3889857Sobrien * BIOS. 3989857Sobrien */ 4089857Sobrien 4189857Sobrien/* If you boot an IGP board with a discrete card as the primary, 4289857Sobrien * the IGP rom is not accessible via the rom bar as the IGP rom is 4389857Sobrien * part of the system bios. On boot, the system bios puts a 4489857Sobrien * copy of the igp rom at the start of vram if a discrete card is 4589857Sobrien * present. 4689857Sobrien */ 4789857Sobrienstatic bool igp_read_bios_from_vram(struct radeon_device *rdev) 4889857Sobrien{ 4989857Sobrien drm_local_map_t bios_map; 5089857Sobrien uint8_t __iomem *bios; 5189857Sobrien resource_size_t vram_base; 5289857Sobrien resource_size_t size = 256 * 1024; /* ??? */ 5389857Sobrien 5489857Sobrien DRM_INFO("%s: ===> Try IGP's VRAM...\n", __func__); 5589857Sobrien 5689857Sobrien if (!(rdev->flags & RADEON_IS_IGP)) 5789857Sobrien if (!radeon_card_posted(rdev)) { 5889857Sobrien DRM_INFO("%s: not POSTed discrete card detected, skipping this method...\n", 5989857Sobrien __func__); 6089857Sobrien return false; 6189857Sobrien } 6289857Sobrien 6389857Sobrien rdev->bios = NULL; 6489857Sobrien vram_base = drm_get_resource_start(rdev->ddev, 0); 6589857Sobrien DRM_INFO("%s: VRAM base address: 0x%jx\n", __func__, (uintmax_t)vram_base); 6689857Sobrien 6789857Sobrien bios_map.offset = vram_base; 6889857Sobrien bios_map.size = size; 6989857Sobrien bios_map.type = 0; 7089857Sobrien bios_map.flags = 0; 7189857Sobrien bios_map.mtrr = 0; 7289857Sobrien drm_core_ioremap(&bios_map, rdev->ddev); 7389857Sobrien if (bios_map.virtual == NULL) { 7489857Sobrien DRM_INFO("%s: failed to ioremap\n", __func__); 7589857Sobrien return false; 7689857Sobrien } 7789857Sobrien bios = bios_map.virtual; 7889857Sobrien size = bios_map.size; 7989857Sobrien DRM_INFO("%s: Map address: %p (%ju bytes)\n", __func__, bios, (uintmax_t)size); 8089857Sobrien 8189857Sobrien if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { 8289857Sobrien if (size == 0) { 8389857Sobrien DRM_INFO("%s: Incorrect BIOS size\n", __func__); 8489857Sobrien } else { 8589857Sobrien DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", 8689857Sobrien __func__, bios[0], bios[1]); 8789857Sobrien } 8889857Sobrien drm_core_ioremapfree(&bios_map, rdev->ddev); 8989857Sobrien return false; 9089857Sobrien } 9189857Sobrien rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK); 9289857Sobrien if (rdev->bios == NULL) { 9389857Sobrien drm_core_ioremapfree(&bios_map, rdev->ddev); 9489857Sobrien return false; 9589857Sobrien } 9689857Sobrien memcpy_fromio(rdev->bios, bios, size); 9789857Sobrien drm_core_ioremapfree(&bios_map, rdev->ddev); 9889857Sobrien return true; 9989857Sobrien} 10089857Sobrien 10189857Sobrienstatic bool radeon_read_bios(struct radeon_device *rdev) 10289857Sobrien{ 10389857Sobrien device_t vga_dev; 10489857Sobrien uint8_t __iomem *bios; 10589857Sobrien size_t size; 10689857Sobrien 10789857Sobrien DRM_INFO("%s: ===> Try PCI Expansion ROM...\n", __func__); 10889857Sobrien 10989857Sobrien vga_dev = device_get_parent(rdev->dev); 11089857Sobrien rdev->bios = NULL; 11189857Sobrien /* XXX: some cards may return 0 for rom size? ddx has a workaround */ 11289857Sobrien bios = vga_pci_map_bios(vga_dev, &size); 11389857Sobrien if (!bios) { 11489857Sobrien return false; 11589857Sobrien } 11689857Sobrien DRM_INFO("%s: Map address: %p (%zu bytes)\n", __func__, bios, size); 11789857Sobrien 11889857Sobrien if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { 11989857Sobrien if (size == 0) { 12089857Sobrien DRM_INFO("%s: Incorrect BIOS size\n", __func__); 12189857Sobrien } else { 12289857Sobrien DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", 12389857Sobrien __func__, bios[0], bios[1]); 12489857Sobrien } 12589857Sobrien vga_pci_unmap_bios(vga_dev, bios); 12689857Sobrien } 12789857Sobrien rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK); 12889857Sobrien memcpy(rdev->bios, bios, size); 12989857Sobrien vga_pci_unmap_bios(vga_dev, bios); 13089857Sobrien return true; 13189857Sobrien} 13289857Sobrien 13389857Sobrien/* ATRM is used to get the BIOS on the discrete cards in 13489857Sobrien * dual-gpu systems. 13589857Sobrien */ 13689857Sobrien/* retrieve the ROM in 4k blocks */ 13789857Sobrien#define ATRM_BIOS_PAGE 4096 13889857Sobrien/** 13989857Sobrien * radeon_atrm_call - fetch a chunk of the vbios 14089857Sobrien * 14189857Sobrien * @atrm_handle: acpi ATRM handle 14289857Sobrien * @bios: vbios image pointer 14389857Sobrien * @offset: offset of vbios image data to fetch 14489857Sobrien * @len: length of vbios image data to fetch 14589857Sobrien * 14689857Sobrien * Executes ATRM to fetch a chunk of the discrete 14789857Sobrien * vbios image on PX systems (all asics). 14889857Sobrien * Returns the length of the buffer fetched. 14989857Sobrien */ 15089857Sobrienstatic int radeon_atrm_call(ACPI_HANDLE atrm_handle, uint8_t *bios, 15189857Sobrien int offset, int len) 15289857Sobrien{ 15389857Sobrien ACPI_STATUS status; 15489857Sobrien ACPI_OBJECT atrm_arg_elements[2], *obj; 15589857Sobrien ACPI_OBJECT_LIST atrm_arg; 15689857Sobrien ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL}; 15789857Sobrien 15889857Sobrien atrm_arg.Count = 2; 15989857Sobrien atrm_arg.Pointer = &atrm_arg_elements[0]; 16089857Sobrien 16189857Sobrien atrm_arg_elements[0].Type = ACPI_TYPE_INTEGER; 16289857Sobrien atrm_arg_elements[0].Integer.Value = offset; 16389857Sobrien 16489857Sobrien atrm_arg_elements[1].Type = ACPI_TYPE_INTEGER; 16589857Sobrien atrm_arg_elements[1].Integer.Value = len; 16689857Sobrien 16789857Sobrien status = AcpiEvaluateObject(atrm_handle, NULL, &atrm_arg, &buffer); 16889857Sobrien if (ACPI_FAILURE(status)) { 16989857Sobrien DRM_ERROR("failed to evaluate ATRM got %s\n", AcpiFormatException(status)); 17089857Sobrien return -ENODEV; 17189857Sobrien } 17289857Sobrien 17389857Sobrien obj = (ACPI_OBJECT *)buffer.Pointer; 17489857Sobrien memcpy(bios+offset, obj->Buffer.Pointer, obj->Buffer.Length); 17589857Sobrien len = obj->Buffer.Length; 17689857Sobrien AcpiOsFree(buffer.Pointer); 17789857Sobrien return len; 17889857Sobrien} 17989857Sobrien 18089857Sobrienstatic bool radeon_atrm_get_bios(struct radeon_device *rdev) 18189857Sobrien{ 18289857Sobrien int ret; 18389857Sobrien int size = 256 * 1024; 18489857Sobrien int i; 18589857Sobrien device_t dev; 18689857Sobrien ACPI_HANDLE dhandle, atrm_handle; 18789857Sobrien ACPI_STATUS status; 18889857Sobrien bool found = false; 18989857Sobrien 19089857Sobrien DRM_INFO("%s: ===> Try ATRM...\n", __func__); 19189857Sobrien 19289857Sobrien /* ATRM is for the discrete card only */ 19389857Sobrien if (rdev->flags & RADEON_IS_IGP) { 19489857Sobrien DRM_INFO("%s: IGP card detected, skipping this method...\n", 19589857Sobrien __func__); 19689857Sobrien return false; 19789857Sobrien } 19889857Sobrien 19989857Sobrien#ifdef DUMBBELL_WIP 20089857Sobrien while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { 20189857Sobrien#endif /* DUMBBELL_WIP */ 20289857Sobrien if ((dev = pci_find_class(PCIC_DISPLAY, PCIS_DISPLAY_VGA)) != NULL) { 20389857Sobrien DRM_INFO("%s: pci_find_class() found: %d:%d:%d:%d, vendor=%04x, device=%04x\n", 20489857Sobrien __func__, 20589857Sobrien pci_get_domain(dev), 20689857Sobrien pci_get_bus(dev), 20789857Sobrien pci_get_slot(dev), 20889857Sobrien pci_get_function(dev), 20989857Sobrien pci_get_vendor(dev), 21089857Sobrien pci_get_device(dev)); 21189857Sobrien DRM_INFO("%s: Get ACPI device handle\n", __func__); 21289857Sobrien dhandle = acpi_get_handle(dev); 21389857Sobrien#ifdef DUMBBELL_WIP 21489857Sobrien if (!dhandle) 21589857Sobrien continue; 21689857Sobrien#endif /* DUMBBELL_WIP */ 21789857Sobrien if (!dhandle) 21889857Sobrien return false; 21989857Sobrien 22089857Sobrien DRM_INFO("%s: Get ACPI handle for \"ATRM\"\n", __func__); 22189857Sobrien status = AcpiGetHandle(dhandle, "ATRM", &atrm_handle); 22289857Sobrien if (!ACPI_FAILURE(status)) { 22389857Sobrien found = true; 22489857Sobrien#ifdef DUMBBELL_WIP 22589857Sobrien break; 22689857Sobrien#endif /* DUMBBELL_WIP */ 22789857Sobrien } else { 22889857Sobrien DRM_INFO("%s: Failed to get \"ATRM\" handle: %s\n", 22989857Sobrien __func__, AcpiFormatException(status)); 23089857Sobrien } 23189857Sobrien } 23289857Sobrien 23389857Sobrien if (!found) 23489857Sobrien return false; 23589857Sobrien 23689857Sobrien rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK); 23789857Sobrien if (!rdev->bios) { 23889857Sobrien DRM_ERROR("Unable to allocate bios\n"); 23989857Sobrien return false; 24089857Sobrien } 24189857Sobrien 24289857Sobrien for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { 24389857Sobrien DRM_INFO("%s: Call radeon_atrm_call()\n", __func__); 24489857Sobrien ret = radeon_atrm_call(atrm_handle, 24589857Sobrien rdev->bios, 24689857Sobrien (i * ATRM_BIOS_PAGE), 24789857Sobrien ATRM_BIOS_PAGE); 24889857Sobrien if (ret < ATRM_BIOS_PAGE) 24989857Sobrien break; 25089857Sobrien } 25189857Sobrien 25289857Sobrien if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { 25389857Sobrien if (i == 0) { 25489857Sobrien DRM_INFO("%s: Incorrect BIOS size\n", __func__); 25589857Sobrien } else { 25689857Sobrien DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", 25789857Sobrien __func__, rdev->bios[0], rdev->bios[1]); 25889857Sobrien } 25989857Sobrien free(rdev->bios, DRM_MEM_DRIVER); 26089857Sobrien return false; 26189857Sobrien } 26289857Sobrien return true; 26389857Sobrien} 26489857Sobrien 26589857Sobrienstatic bool ni_read_disabled_bios(struct radeon_device *rdev) 26689857Sobrien{ 26789857Sobrien u32 bus_cntl; 26889857Sobrien u32 d1vga_control; 26989857Sobrien u32 d2vga_control; 27089857Sobrien u32 vga_render_control; 27189857Sobrien u32 rom_cntl; 27289857Sobrien bool r; 27389857Sobrien 27489857Sobrien DRM_INFO("%s: ===> Try disabled BIOS (ni)...\n", __func__); 27589857Sobrien 27689857Sobrien bus_cntl = RREG32(R600_BUS_CNTL); 27789857Sobrien d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 27889857Sobrien d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 27989857Sobrien vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 28089857Sobrien rom_cntl = RREG32(R600_ROM_CNTL); 28189857Sobrien 28289857Sobrien /* enable the rom */ 28389857Sobrien WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 28489857Sobrien /* Disable VGA mode */ 28589857Sobrien WREG32(AVIVO_D1VGA_CONTROL, 28689857Sobrien (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 28789857Sobrien AVIVO_DVGA_CONTROL_TIMING_SELECT))); 28889857Sobrien WREG32(AVIVO_D2VGA_CONTROL, 28989857Sobrien (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 29089857Sobrien AVIVO_DVGA_CONTROL_TIMING_SELECT))); 29189857Sobrien WREG32(AVIVO_VGA_RENDER_CONTROL, 29289857Sobrien (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 29389857Sobrien WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); 29489857Sobrien 29589857Sobrien r = radeon_read_bios(rdev); 29689857Sobrien 29789857Sobrien /* restore regs */ 29889857Sobrien WREG32(R600_BUS_CNTL, bus_cntl); 29989857Sobrien WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 30089857Sobrien WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 30189857Sobrien WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 30289857Sobrien WREG32(R600_ROM_CNTL, rom_cntl); 30389857Sobrien return r; 30489857Sobrien} 30589857Sobrien 30689857Sobrienstatic bool r700_read_disabled_bios(struct radeon_device *rdev) 30789857Sobrien{ 30889857Sobrien uint32_t viph_control; 30989857Sobrien uint32_t bus_cntl; 31089857Sobrien uint32_t d1vga_control; 31189857Sobrien uint32_t d2vga_control; 31289857Sobrien uint32_t vga_render_control; 31389857Sobrien uint32_t rom_cntl; 31489857Sobrien uint32_t cg_spll_func_cntl = 0; 31589857Sobrien uint32_t cg_spll_status; 31689857Sobrien bool r; 31789857Sobrien 31889857Sobrien DRM_INFO("%s: ===> Try disabled BIOS (r700)...\n", __func__); 31989857Sobrien 32089857Sobrien viph_control = RREG32(RADEON_VIPH_CONTROL); 32189857Sobrien bus_cntl = RREG32(R600_BUS_CNTL); 32289857Sobrien d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 32389857Sobrien d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 32489857Sobrien vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 32589857Sobrien rom_cntl = RREG32(R600_ROM_CNTL); 32689857Sobrien 32789857Sobrien /* disable VIP */ 32889857Sobrien WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 32989857Sobrien /* enable the rom */ 33089857Sobrien WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 33189857Sobrien /* Disable VGA mode */ 33289857Sobrien WREG32(AVIVO_D1VGA_CONTROL, 33389857Sobrien (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 33489857Sobrien AVIVO_DVGA_CONTROL_TIMING_SELECT))); 33589857Sobrien WREG32(AVIVO_D2VGA_CONTROL, 33689857Sobrien (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 33789857Sobrien AVIVO_DVGA_CONTROL_TIMING_SELECT))); 33889857Sobrien WREG32(AVIVO_VGA_RENDER_CONTROL, 33989857Sobrien (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 34089857Sobrien 34189857Sobrien if (rdev->family == CHIP_RV730) { 34289857Sobrien cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL); 34389857Sobrien 34489857Sobrien /* enable bypass mode */ 34589857Sobrien WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | 34689857Sobrien R600_SPLL_BYPASS_EN)); 34789857Sobrien 34889857Sobrien /* wait for SPLL_CHG_STATUS to change to 1 */ 34989857Sobrien cg_spll_status = 0; 35089857Sobrien while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) 35189857Sobrien cg_spll_status = RREG32(R600_CG_SPLL_STATUS); 35289857Sobrien 35389857Sobrien WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); 35489857Sobrien } else 35589857Sobrien WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); 35689857Sobrien 35789857Sobrien r = radeon_read_bios(rdev); 35889857Sobrien 35989857Sobrien /* restore regs */ 36089857Sobrien if (rdev->family == CHIP_RV730) { 36189857Sobrien WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); 36289857Sobrien 36389857Sobrien /* wait for SPLL_CHG_STATUS to change to 1 */ 36489857Sobrien cg_spll_status = 0; 36589857Sobrien while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) 36689857Sobrien cg_spll_status = RREG32(R600_CG_SPLL_STATUS); 36789857Sobrien } 36889857Sobrien WREG32(RADEON_VIPH_CONTROL, viph_control); 36989857Sobrien WREG32(R600_BUS_CNTL, bus_cntl); 37089857Sobrien WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 37189857Sobrien WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 37289857Sobrien WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 37389857Sobrien WREG32(R600_ROM_CNTL, rom_cntl); 37489857Sobrien return r; 37589857Sobrien} 37689857Sobrien 37789857Sobrienstatic bool r600_read_disabled_bios(struct radeon_device *rdev) 37889857Sobrien{ 37989857Sobrien uint32_t viph_control; 38089857Sobrien uint32_t bus_cntl; 38189857Sobrien uint32_t d1vga_control; 38289857Sobrien uint32_t d2vga_control; 38389857Sobrien uint32_t vga_render_control; 38489857Sobrien uint32_t rom_cntl; 38589857Sobrien uint32_t general_pwrmgt; 38689857Sobrien uint32_t low_vid_lower_gpio_cntl; 38789857Sobrien uint32_t medium_vid_lower_gpio_cntl; 38889857Sobrien uint32_t high_vid_lower_gpio_cntl; 38989857Sobrien uint32_t ctxsw_vid_lower_gpio_cntl; 39089857Sobrien uint32_t lower_gpio_enable; 39189857Sobrien bool r; 39289857Sobrien 39389857Sobrien DRM_INFO("%s: ===> Try disabled BIOS (r600)...\n", __func__); 39489857Sobrien 39589857Sobrien viph_control = RREG32(RADEON_VIPH_CONTROL); 39689857Sobrien bus_cntl = RREG32(R600_BUS_CNTL); 39789857Sobrien d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 39889857Sobrien d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 39989857Sobrien vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 40089857Sobrien rom_cntl = RREG32(R600_ROM_CNTL); 40189857Sobrien general_pwrmgt = RREG32(R600_GENERAL_PWRMGT); 40289857Sobrien low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL); 40389857Sobrien medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); 40489857Sobrien high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL); 40589857Sobrien ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL); 40689857Sobrien lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE); 40789857Sobrien 40889857Sobrien /* disable VIP */ 40989857Sobrien WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 41089857Sobrien /* enable the rom */ 41189857Sobrien WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 41289857Sobrien /* Disable VGA mode */ 41389857Sobrien WREG32(AVIVO_D1VGA_CONTROL, 41489857Sobrien (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 41589857Sobrien AVIVO_DVGA_CONTROL_TIMING_SELECT))); 41689857Sobrien WREG32(AVIVO_D2VGA_CONTROL, 41789857Sobrien (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 41889857Sobrien AVIVO_DVGA_CONTROL_TIMING_SELECT))); 41989857Sobrien WREG32(AVIVO_VGA_RENDER_CONTROL, 42089857Sobrien (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 42189857Sobrien 42289857Sobrien WREG32(R600_ROM_CNTL, 42389857Sobrien ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | 42489857Sobrien (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | 42589857Sobrien R600_SCK_OVERWRITE)); 42689857Sobrien 42789857Sobrien WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); 42889857Sobrien WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, 42989857Sobrien (low_vid_lower_gpio_cntl & ~0x400)); 43089857Sobrien WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, 43189857Sobrien (medium_vid_lower_gpio_cntl & ~0x400)); 43289857Sobrien WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, 43389857Sobrien (high_vid_lower_gpio_cntl & ~0x400)); 43489857Sobrien WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, 43589857Sobrien (ctxsw_vid_lower_gpio_cntl & ~0x400)); 43689857Sobrien WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); 43789857Sobrien 43889857Sobrien r = radeon_read_bios(rdev); 43989857Sobrien 44089857Sobrien /* restore regs */ 44189857Sobrien WREG32(RADEON_VIPH_CONTROL, viph_control); 442218822Sdim WREG32(R600_BUS_CNTL, bus_cntl); 44389857Sobrien WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 44489857Sobrien WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 44589857Sobrien WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 44689857Sobrien WREG32(R600_ROM_CNTL, rom_cntl); 447218822Sdim WREG32(R600_GENERAL_PWRMGT, general_pwrmgt); 448218822Sdim WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); 44989857Sobrien WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); 45089857Sobrien WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); 45189857Sobrien WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); 45289857Sobrien WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); 45389857Sobrien return r; 454218822Sdim} 45589857Sobrien 45689857Sobrienstatic bool avivo_read_disabled_bios(struct radeon_device *rdev) 45789857Sobrien{ 45889857Sobrien uint32_t seprom_cntl1; 45989857Sobrien uint32_t viph_control; 46089857Sobrien uint32_t bus_cntl; 46189857Sobrien uint32_t d1vga_control; 462218822Sdim uint32_t d2vga_control; 463218822Sdim uint32_t vga_render_control; 464218822Sdim uint32_t gpiopad_a; 46589857Sobrien uint32_t gpiopad_en; 46689857Sobrien uint32_t gpiopad_mask; 46789857Sobrien bool r; 46889857Sobrien 469218822Sdim DRM_INFO("%s: ===> Try disabled BIOS (avivo)...\n", __func__); 470218822Sdim 471218822Sdim seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); 472218822Sdim viph_control = RREG32(RADEON_VIPH_CONTROL); 47389857Sobrien bus_cntl = RREG32(RV370_BUS_CNTL); 47489857Sobrien d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 47589857Sobrien d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 47689857Sobrien vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 477218822Sdim gpiopad_a = RREG32(RADEON_GPIOPAD_A); 478218822Sdim gpiopad_en = RREG32(RADEON_GPIOPAD_EN); 47989857Sobrien gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK); 48089857Sobrien 48189857Sobrien WREG32(RADEON_SEPROM_CNTL1, 482218822Sdim ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 483218822Sdim (0xc << RADEON_SCK_PRESCALE_SHIFT))); 484218822Sdim WREG32(RADEON_GPIOPAD_A, 0); 48589857Sobrien WREG32(RADEON_GPIOPAD_EN, 0); 48689857Sobrien WREG32(RADEON_GPIOPAD_MASK, 0); 48789857Sobrien 48889857Sobrien /* disable VIP */ 48989857Sobrien WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 49089857Sobrien 49189857Sobrien /* enable the rom */ 49289857Sobrien WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); 49389857Sobrien 49489857Sobrien /* Disable VGA mode */ 49589857Sobrien WREG32(AVIVO_D1VGA_CONTROL, 49689857Sobrien (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 49789857Sobrien AVIVO_DVGA_CONTROL_TIMING_SELECT))); 49889857Sobrien WREG32(AVIVO_D2VGA_CONTROL, 499218822Sdim (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 500218822Sdim AVIVO_DVGA_CONTROL_TIMING_SELECT))); 501218822Sdim WREG32(AVIVO_VGA_RENDER_CONTROL, 502218822Sdim (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 50389857Sobrien 50489857Sobrien r = radeon_read_bios(rdev); 50589857Sobrien 50689857Sobrien /* restore regs */ 507218822Sdim WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); 508218822Sdim WREG32(RADEON_VIPH_CONTROL, viph_control); 50989857Sobrien WREG32(RV370_BUS_CNTL, bus_cntl); 51089857Sobrien WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 51189857Sobrien WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 51289857Sobrien WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 51389857Sobrien WREG32(RADEON_GPIOPAD_A, gpiopad_a); 51489857Sobrien WREG32(RADEON_GPIOPAD_EN, gpiopad_en); 51589857Sobrien WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask); 51689857Sobrien return r; 51789857Sobrien} 51889857Sobrien 51989857Sobrienstatic bool legacy_read_disabled_bios(struct radeon_device *rdev) 52089857Sobrien{ 52189857Sobrien uint32_t seprom_cntl1; 52289857Sobrien uint32_t viph_control; 52389857Sobrien uint32_t bus_cntl; 524104834Sobrien uint32_t crtc_gen_cntl; 525104834Sobrien uint32_t crtc2_gen_cntl; 526104834Sobrien uint32_t crtc_ext_cntl; 527104834Sobrien uint32_t fp2_gen_cntl; 528104834Sobrien bool r; 529104834Sobrien 530104834Sobrien DRM_INFO("%s: ===> Try disabled BIOS (legacy)...\n", __func__); 531104834Sobrien 532104834Sobrien seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); 533104834Sobrien viph_control = RREG32(RADEON_VIPH_CONTROL); 53489857Sobrien if (rdev->flags & RADEON_IS_PCIE) 535218822Sdim bus_cntl = RREG32(RV370_BUS_CNTL); 536218822Sdim else 537218822Sdim bus_cntl = RREG32(RADEON_BUS_CNTL); 53889857Sobrien crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 539218822Sdim crtc2_gen_cntl = 0; 540218822Sdim crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 541218822Sdim fp2_gen_cntl = 0; 542218822Sdim 543218822Sdim#define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 544218822Sdim 545218822Sdim if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { 54689857Sobrien fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 547218822Sdim } 548218822Sdim 54989857Sobrien if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 550218822Sdim crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 55189857Sobrien } 55289857Sobrien 55389857Sobrien WREG32(RADEON_SEPROM_CNTL1, 55489857Sobrien ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 55589857Sobrien (0xc << RADEON_SCK_PRESCALE_SHIFT))); 55689857Sobrien 55789857Sobrien /* disable VIP */ 55889857Sobrien WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 55989857Sobrien 56089857Sobrien /* enable the rom */ 56189857Sobrien if (rdev->flags & RADEON_IS_PCIE) 56289857Sobrien WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); 56389857Sobrien else 56489857Sobrien WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 56589857Sobrien 566 /* Turn off mem requests and CRTC for both controllers */ 567 WREG32(RADEON_CRTC_GEN_CNTL, 568 ((crtc_gen_cntl & ~RADEON_CRTC_EN) | 569 (RADEON_CRTC_DISP_REQ_EN_B | 570 RADEON_CRTC_EXT_DISP_EN))); 571 if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 572 WREG32(RADEON_CRTC2_GEN_CNTL, 573 ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | 574 RADEON_CRTC2_DISP_REQ_EN_B)); 575 } 576 /* Turn off CRTC */ 577 WREG32(RADEON_CRTC_EXT_CNTL, 578 ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | 579 (RADEON_CRTC_SYNC_TRISTAT | 580 RADEON_CRTC_DISPLAY_DIS))); 581 582 if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { 583 WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); 584 } 585 586 r = radeon_read_bios(rdev); 587 588 /* restore regs */ 589 WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); 590 WREG32(RADEON_VIPH_CONTROL, viph_control); 591 if (rdev->flags & RADEON_IS_PCIE) 592 WREG32(RV370_BUS_CNTL, bus_cntl); 593 else 594 WREG32(RADEON_BUS_CNTL, bus_cntl); 595 WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); 596 if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 597 WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 598 } 599 WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 600 if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { 601 WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 602 } 603 return r; 604} 605 606static bool radeon_read_disabled_bios(struct radeon_device *rdev) 607{ 608 if (rdev->flags & RADEON_IS_IGP) 609 return igp_read_bios_from_vram(rdev); 610 else if (rdev->family >= CHIP_BARTS) 611 return ni_read_disabled_bios(rdev); 612 else if (rdev->family >= CHIP_RV770) 613 return r700_read_disabled_bios(rdev); 614 else if (rdev->family >= CHIP_R600) 615 return r600_read_disabled_bios(rdev); 616 else if (rdev->family >= CHIP_RS600) 617 return avivo_read_disabled_bios(rdev); 618 else 619 return legacy_read_disabled_bios(rdev); 620} 621 622static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) 623{ 624 bool ret = false; 625 ACPI_TABLE_HEADER *hdr; 626 ACPI_SIZE tbl_size; 627 UEFI_ACPI_VFCT *vfct; 628 GOP_VBIOS_CONTENT *vbios; 629 VFCT_IMAGE_HEADER *vhdr; 630 ACPI_STATUS status; 631 632 DRM_INFO("%s: ===> Try VFCT...\n", __func__); 633 634 DRM_INFO("%s: Get \"VFCT\" ACPI table\n", __func__); 635 status = AcpiGetTable("VFCT", 1, &hdr); 636 if (!ACPI_SUCCESS(status)) { 637 DRM_INFO("%s: Failed to get \"VFCT\" table: %s\n", 638 __func__, AcpiFormatException(status)); 639 return false; 640 } 641 tbl_size = hdr->Length; 642 if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { 643 DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); 644 goto out_unmap; 645 } 646 647 vfct = (UEFI_ACPI_VFCT *)hdr; 648 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { 649 DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); 650 goto out_unmap; 651 } 652 653 vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); 654 vhdr = &vbios->VbiosHeader; 655 DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", 656 vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, 657 vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); 658 659 if (vhdr->PCIBus != rdev->ddev->pci_bus || 660 vhdr->PCIDevice != rdev->ddev->pci_slot || 661 vhdr->PCIFunction != rdev->ddev->pci_func || 662 vhdr->VendorID != rdev->ddev->pci_vendor || 663 vhdr->DeviceID != rdev->ddev->pci_device) { 664 DRM_INFO("ACPI VFCT table is not for this card\n"); 665 goto out_unmap; 666 }; 667 668 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { 669 DRM_ERROR("ACPI VFCT image truncated\n"); 670 goto out_unmap; 671 } 672 673 rdev->bios = malloc(vhdr->ImageLength, DRM_MEM_DRIVER, M_WAITOK); 674 memcpy(rdev->bios, &vbios->VbiosContent, vhdr->ImageLength); 675 ret = !!rdev->bios; 676 677out_unmap: 678 return ret; 679} 680 681bool radeon_get_bios(struct radeon_device *rdev) 682{ 683 bool r; 684 uint16_t tmp; 685 686 r = radeon_atrm_get_bios(rdev); 687 if (r == false) 688 r = radeon_acpi_vfct_bios(rdev); 689 if (r == false) 690 r = igp_read_bios_from_vram(rdev); 691 if (r == false) 692 r = radeon_read_bios(rdev); 693 if (r == false) { 694 r = radeon_read_disabled_bios(rdev); 695 } 696 if (r == false || rdev->bios == NULL) { 697 DRM_ERROR("Unable to locate a BIOS ROM\n"); 698 rdev->bios = NULL; 699 return false; 700 } 701 if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { 702 DRM_ERROR("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]); 703 goto free_bios; 704 } 705 706 tmp = RBIOS16(0x18); 707 if (RBIOS8(tmp + 0x14) != 0x0) { 708 DRM_INFO("Not an x86 BIOS ROM, not using.\n"); 709 goto free_bios; 710 } 711 712 rdev->bios_header_start = RBIOS16(0x48); 713 if (!rdev->bios_header_start) { 714 goto free_bios; 715 } 716 tmp = rdev->bios_header_start + 4; 717 if (!memcmp(rdev->bios + tmp, "ATOM", 4) || 718 !memcmp(rdev->bios + tmp, "MOTA", 4)) { 719 rdev->is_atom_bios = true; 720 } else { 721 rdev->is_atom_bios = false; 722 } 723 724 DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); 725 return true; 726free_bios: 727 free(rdev->bios, DRM_MEM_DRIVER); 728 rdev->bios = NULL; 729 return false; 730} 731