1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2008 Advanced Micro Devices, Inc. 3254885Sdumbbell * Copyright 2008 Red Hat Inc. 4254885Sdumbbell * Copyright 2009 Jerome Glisse. 5254885Sdumbbell * 6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 7254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 8254885Sdumbbell * to deal in the Software without restriction, including without limitation 9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 11254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 12254885Sdumbbell * 13254885Sdumbbell * The above copyright notice and this permission notice shall be included in 14254885Sdumbbell * all copies or substantial portions of the Software. 15254885Sdumbbell * 16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 23254885Sdumbbell * 24254885Sdumbbell * Authors: Dave Airlie 25254885Sdumbbell * Alex Deucher 26254885Sdumbbell * Jerome Glisse 27254885Sdumbbell */ 28254885Sdumbbell 29254885Sdumbbell#include <sys/cdefs.h> 30254885Sdumbbell__FBSDID("$FreeBSD: releng/10.2/sys/dev/drm2/radeon/radeon_bios.c 282199 2015-04-28 19:35:05Z dumbbell $"); 31254885Sdumbbell 32254885Sdumbbell#include <dev/drm2/drmP.h> 33254885Sdumbbell#include "radeon_reg.h" 34254885Sdumbbell#include "radeon.h" 35254885Sdumbbell#include "atom.h" 36254885Sdumbbell 37254885Sdumbbell/* 38254885Sdumbbell * BIOS. 39254885Sdumbbell */ 40254885Sdumbbell 41254885Sdumbbell/* If you boot an IGP board with a discrete card as the primary, 42254885Sdumbbell * the IGP rom is not accessible via the rom bar as the IGP rom is 43254885Sdumbbell * part of the system bios. On boot, the system bios puts a 44254885Sdumbbell * copy of the igp rom at the start of vram if a discrete card is 45254885Sdumbbell * present. 46254885Sdumbbell */ 47254885Sdumbbellstatic bool igp_read_bios_from_vram(struct radeon_device *rdev) 48254885Sdumbbell{ 49282199Sdumbbell struct drm_local_map bios_map; 50254885Sdumbbell uint8_t __iomem *bios; 51254885Sdumbbell resource_size_t vram_base; 52254885Sdumbbell resource_size_t size = 256 * 1024; /* ??? */ 53254885Sdumbbell 54254885Sdumbbell DRM_INFO("%s: ===> Try IGP's VRAM...\n", __func__); 55254885Sdumbbell 56254885Sdumbbell if (!(rdev->flags & RADEON_IS_IGP)) 57254885Sdumbbell if (!radeon_card_posted(rdev)) { 58254885Sdumbbell DRM_INFO("%s: not POSTed discrete card detected, skipping this method...\n", 59254885Sdumbbell __func__); 60254885Sdumbbell return false; 61254885Sdumbbell } 62254885Sdumbbell 63254885Sdumbbell rdev->bios = NULL; 64254885Sdumbbell vram_base = drm_get_resource_start(rdev->ddev, 0); 65254885Sdumbbell DRM_INFO("%s: VRAM base address: 0x%jx\n", __func__, (uintmax_t)vram_base); 66254885Sdumbbell 67254885Sdumbbell bios_map.offset = vram_base; 68254885Sdumbbell bios_map.size = size; 69254885Sdumbbell bios_map.type = 0; 70254885Sdumbbell bios_map.flags = 0; 71254885Sdumbbell bios_map.mtrr = 0; 72254885Sdumbbell drm_core_ioremap(&bios_map, rdev->ddev); 73282199Sdumbbell if (bios_map.handle == NULL) { 74254885Sdumbbell DRM_INFO("%s: failed to ioremap\n", __func__); 75254885Sdumbbell return false; 76254885Sdumbbell } 77282199Sdumbbell bios = bios_map.handle; 78254885Sdumbbell size = bios_map.size; 79254885Sdumbbell DRM_INFO("%s: Map address: %p (%ju bytes)\n", __func__, bios, (uintmax_t)size); 80254885Sdumbbell 81254885Sdumbbell if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { 82254885Sdumbbell if (size == 0) { 83254885Sdumbbell DRM_INFO("%s: Incorrect BIOS size\n", __func__); 84254885Sdumbbell } else { 85254885Sdumbbell DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", 86254885Sdumbbell __func__, bios[0], bios[1]); 87254885Sdumbbell } 88254885Sdumbbell drm_core_ioremapfree(&bios_map, rdev->ddev); 89254885Sdumbbell return false; 90254885Sdumbbell } 91282199Sdumbbell rdev->bios = malloc(size, DRM_MEM_DRIVER, M_NOWAIT); 92254885Sdumbbell if (rdev->bios == NULL) { 93254885Sdumbbell drm_core_ioremapfree(&bios_map, rdev->ddev); 94254885Sdumbbell return false; 95254885Sdumbbell } 96254885Sdumbbell memcpy_fromio(rdev->bios, bios, size); 97254885Sdumbbell drm_core_ioremapfree(&bios_map, rdev->ddev); 98254885Sdumbbell return true; 99254885Sdumbbell} 100254885Sdumbbell 101254885Sdumbbellstatic bool radeon_read_bios(struct radeon_device *rdev) 102254885Sdumbbell{ 103255572Sdumbbell device_t vga_dev; 104254885Sdumbbell uint8_t __iomem *bios; 105254885Sdumbbell size_t size; 106254885Sdumbbell 107254885Sdumbbell DRM_INFO("%s: ===> Try PCI Expansion ROM...\n", __func__); 108254885Sdumbbell 109255572Sdumbbell vga_dev = device_get_parent(rdev->dev); 110254885Sdumbbell rdev->bios = NULL; 111254885Sdumbbell /* XXX: some cards may return 0 for rom size? ddx has a workaround */ 112255572Sdumbbell bios = vga_pci_map_bios(vga_dev, &size); 113254885Sdumbbell if (!bios) { 114254885Sdumbbell return false; 115254885Sdumbbell } 116254885Sdumbbell DRM_INFO("%s: Map address: %p (%zu bytes)\n", __func__, bios, size); 117254885Sdumbbell 118254885Sdumbbell if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { 119254885Sdumbbell if (size == 0) { 120254885Sdumbbell DRM_INFO("%s: Incorrect BIOS size\n", __func__); 121254885Sdumbbell } else { 122254885Sdumbbell DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", 123254885Sdumbbell __func__, bios[0], bios[1]); 124254885Sdumbbell } 125255572Sdumbbell vga_pci_unmap_bios(vga_dev, bios); 126255587Sdumbbell return false; 127254885Sdumbbell } 128282199Sdumbbell rdev->bios = malloc(size, DRM_MEM_DRIVER, M_NOWAIT); 129282199Sdumbbell if (rdev->bios == NULL) { 130282199Sdumbbell vga_pci_unmap_bios(vga_dev, bios); 131282199Sdumbbell return false; 132282199Sdumbbell } 133254885Sdumbbell memcpy(rdev->bios, bios, size); 134255572Sdumbbell vga_pci_unmap_bios(vga_dev, bios); 135254885Sdumbbell return true; 136254885Sdumbbell} 137254885Sdumbbell 138282199Sdumbbell#ifdef CONFIG_ACPI 139254885Sdumbbell/* ATRM is used to get the BIOS on the discrete cards in 140254885Sdumbbell * dual-gpu systems. 141254885Sdumbbell */ 142254885Sdumbbell/* retrieve the ROM in 4k blocks */ 143254885Sdumbbell#define ATRM_BIOS_PAGE 4096 144254885Sdumbbell/** 145254885Sdumbbell * radeon_atrm_call - fetch a chunk of the vbios 146254885Sdumbbell * 147254885Sdumbbell * @atrm_handle: acpi ATRM handle 148254885Sdumbbell * @bios: vbios image pointer 149254885Sdumbbell * @offset: offset of vbios image data to fetch 150254885Sdumbbell * @len: length of vbios image data to fetch 151254885Sdumbbell * 152254885Sdumbbell * Executes ATRM to fetch a chunk of the discrete 153254885Sdumbbell * vbios image on PX systems (all asics). 154254885Sdumbbell * Returns the length of the buffer fetched. 155254885Sdumbbell */ 156254885Sdumbbellstatic int radeon_atrm_call(ACPI_HANDLE atrm_handle, uint8_t *bios, 157254885Sdumbbell int offset, int len) 158254885Sdumbbell{ 159254885Sdumbbell ACPI_STATUS status; 160254885Sdumbbell ACPI_OBJECT atrm_arg_elements[2], *obj; 161254885Sdumbbell ACPI_OBJECT_LIST atrm_arg; 162254885Sdumbbell ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL}; 163254885Sdumbbell 164254885Sdumbbell atrm_arg.Count = 2; 165254885Sdumbbell atrm_arg.Pointer = &atrm_arg_elements[0]; 166254885Sdumbbell 167254885Sdumbbell atrm_arg_elements[0].Type = ACPI_TYPE_INTEGER; 168254885Sdumbbell atrm_arg_elements[0].Integer.Value = offset; 169254885Sdumbbell 170254885Sdumbbell atrm_arg_elements[1].Type = ACPI_TYPE_INTEGER; 171254885Sdumbbell atrm_arg_elements[1].Integer.Value = len; 172254885Sdumbbell 173254885Sdumbbell status = AcpiEvaluateObject(atrm_handle, NULL, &atrm_arg, &buffer); 174254885Sdumbbell if (ACPI_FAILURE(status)) { 175254885Sdumbbell DRM_ERROR("failed to evaluate ATRM got %s\n", AcpiFormatException(status)); 176254885Sdumbbell return -ENODEV; 177254885Sdumbbell } 178254885Sdumbbell 179254885Sdumbbell obj = (ACPI_OBJECT *)buffer.Pointer; 180254885Sdumbbell memcpy(bios+offset, obj->Buffer.Pointer, obj->Buffer.Length); 181254885Sdumbbell len = obj->Buffer.Length; 182254885Sdumbbell AcpiOsFree(buffer.Pointer); 183254885Sdumbbell return len; 184254885Sdumbbell} 185254885Sdumbbell 186254885Sdumbbellstatic bool radeon_atrm_get_bios(struct radeon_device *rdev) 187254885Sdumbbell{ 188254885Sdumbbell int ret; 189254885Sdumbbell int size = 256 * 1024; 190254885Sdumbbell int i; 191254885Sdumbbell device_t dev; 192254885Sdumbbell ACPI_HANDLE dhandle, atrm_handle; 193254885Sdumbbell ACPI_STATUS status; 194254885Sdumbbell bool found = false; 195254885Sdumbbell 196254885Sdumbbell DRM_INFO("%s: ===> Try ATRM...\n", __func__); 197254885Sdumbbell 198254885Sdumbbell /* ATRM is for the discrete card only */ 199254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) { 200254885Sdumbbell DRM_INFO("%s: IGP card detected, skipping this method...\n", 201254885Sdumbbell __func__); 202254885Sdumbbell return false; 203254885Sdumbbell } 204254885Sdumbbell 205282199Sdumbbell#ifdef FREEBSD_WIP 206254885Sdumbbell while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { 207282199Sdumbbell#endif /* FREEBSD_WIP */ 208254885Sdumbbell if ((dev = pci_find_class(PCIC_DISPLAY, PCIS_DISPLAY_VGA)) != NULL) { 209254885Sdumbbell DRM_INFO("%s: pci_find_class() found: %d:%d:%d:%d, vendor=%04x, device=%04x\n", 210254885Sdumbbell __func__, 211254885Sdumbbell pci_get_domain(dev), 212254885Sdumbbell pci_get_bus(dev), 213254885Sdumbbell pci_get_slot(dev), 214254885Sdumbbell pci_get_function(dev), 215254885Sdumbbell pci_get_vendor(dev), 216254885Sdumbbell pci_get_device(dev)); 217254885Sdumbbell DRM_INFO("%s: Get ACPI device handle\n", __func__); 218254885Sdumbbell dhandle = acpi_get_handle(dev); 219282199Sdumbbell#ifdef FREEBSD_WIP 220254885Sdumbbell if (!dhandle) 221254885Sdumbbell continue; 222282199Sdumbbell#endif /* FREEBSD_WIP */ 223254885Sdumbbell if (!dhandle) 224254885Sdumbbell return false; 225254885Sdumbbell 226254885Sdumbbell DRM_INFO("%s: Get ACPI handle for \"ATRM\"\n", __func__); 227254885Sdumbbell status = AcpiGetHandle(dhandle, "ATRM", &atrm_handle); 228254885Sdumbbell if (!ACPI_FAILURE(status)) { 229254885Sdumbbell found = true; 230282199Sdumbbell#ifdef FREEBSD_WIP 231254885Sdumbbell break; 232282199Sdumbbell#endif /* FREEBSD_WIP */ 233254885Sdumbbell } else { 234254885Sdumbbell DRM_INFO("%s: Failed to get \"ATRM\" handle: %s\n", 235254885Sdumbbell __func__, AcpiFormatException(status)); 236254885Sdumbbell } 237254885Sdumbbell } 238254885Sdumbbell 239254885Sdumbbell if (!found) 240254885Sdumbbell return false; 241254885Sdumbbell 242282199Sdumbbell rdev->bios = malloc(size, DRM_MEM_DRIVER, M_NOWAIT); 243254885Sdumbbell if (!rdev->bios) { 244254885Sdumbbell DRM_ERROR("Unable to allocate bios\n"); 245254885Sdumbbell return false; 246254885Sdumbbell } 247254885Sdumbbell 248254885Sdumbbell for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { 249254885Sdumbbell DRM_INFO("%s: Call radeon_atrm_call()\n", __func__); 250254885Sdumbbell ret = radeon_atrm_call(atrm_handle, 251254885Sdumbbell rdev->bios, 252254885Sdumbbell (i * ATRM_BIOS_PAGE), 253254885Sdumbbell ATRM_BIOS_PAGE); 254254885Sdumbbell if (ret < ATRM_BIOS_PAGE) 255254885Sdumbbell break; 256254885Sdumbbell } 257254885Sdumbbell 258254885Sdumbbell if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { 259254885Sdumbbell if (i == 0) { 260254885Sdumbbell DRM_INFO("%s: Incorrect BIOS size\n", __func__); 261254885Sdumbbell } else { 262254885Sdumbbell DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", 263254885Sdumbbell __func__, rdev->bios[0], rdev->bios[1]); 264254885Sdumbbell } 265254885Sdumbbell free(rdev->bios, DRM_MEM_DRIVER); 266254885Sdumbbell return false; 267254885Sdumbbell } 268254885Sdumbbell return true; 269254885Sdumbbell} 270282199Sdumbbell#else 271282199Sdumbbellstatic inline bool radeon_atrm_get_bios(struct radeon_device *rdev) 272282199Sdumbbell{ 273282199Sdumbbell return false; 274282199Sdumbbell} 275282199Sdumbbell#endif 276254885Sdumbbell 277254885Sdumbbellstatic bool ni_read_disabled_bios(struct radeon_device *rdev) 278254885Sdumbbell{ 279254885Sdumbbell u32 bus_cntl; 280254885Sdumbbell u32 d1vga_control; 281254885Sdumbbell u32 d2vga_control; 282254885Sdumbbell u32 vga_render_control; 283254885Sdumbbell u32 rom_cntl; 284254885Sdumbbell bool r; 285254885Sdumbbell 286254885Sdumbbell DRM_INFO("%s: ===> Try disabled BIOS (ni)...\n", __func__); 287254885Sdumbbell 288254885Sdumbbell bus_cntl = RREG32(R600_BUS_CNTL); 289254885Sdumbbell d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 290254885Sdumbbell d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 291254885Sdumbbell vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 292254885Sdumbbell rom_cntl = RREG32(R600_ROM_CNTL); 293254885Sdumbbell 294254885Sdumbbell /* enable the rom */ 295254885Sdumbbell WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 296254885Sdumbbell /* Disable VGA mode */ 297254885Sdumbbell WREG32(AVIVO_D1VGA_CONTROL, 298254885Sdumbbell (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 299254885Sdumbbell AVIVO_DVGA_CONTROL_TIMING_SELECT))); 300254885Sdumbbell WREG32(AVIVO_D2VGA_CONTROL, 301254885Sdumbbell (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 302254885Sdumbbell AVIVO_DVGA_CONTROL_TIMING_SELECT))); 303254885Sdumbbell WREG32(AVIVO_VGA_RENDER_CONTROL, 304254885Sdumbbell (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 305254885Sdumbbell WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); 306254885Sdumbbell 307254885Sdumbbell r = radeon_read_bios(rdev); 308254885Sdumbbell 309254885Sdumbbell /* restore regs */ 310254885Sdumbbell WREG32(R600_BUS_CNTL, bus_cntl); 311254885Sdumbbell WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 312254885Sdumbbell WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 313254885Sdumbbell WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 314254885Sdumbbell WREG32(R600_ROM_CNTL, rom_cntl); 315254885Sdumbbell return r; 316254885Sdumbbell} 317254885Sdumbbell 318254885Sdumbbellstatic bool r700_read_disabled_bios(struct radeon_device *rdev) 319254885Sdumbbell{ 320254885Sdumbbell uint32_t viph_control; 321254885Sdumbbell uint32_t bus_cntl; 322254885Sdumbbell uint32_t d1vga_control; 323254885Sdumbbell uint32_t d2vga_control; 324254885Sdumbbell uint32_t vga_render_control; 325254885Sdumbbell uint32_t rom_cntl; 326254885Sdumbbell uint32_t cg_spll_func_cntl = 0; 327254885Sdumbbell uint32_t cg_spll_status; 328254885Sdumbbell bool r; 329254885Sdumbbell 330254885Sdumbbell DRM_INFO("%s: ===> Try disabled BIOS (r700)...\n", __func__); 331254885Sdumbbell 332254885Sdumbbell viph_control = RREG32(RADEON_VIPH_CONTROL); 333254885Sdumbbell bus_cntl = RREG32(R600_BUS_CNTL); 334254885Sdumbbell d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 335254885Sdumbbell d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 336254885Sdumbbell vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 337254885Sdumbbell rom_cntl = RREG32(R600_ROM_CNTL); 338254885Sdumbbell 339254885Sdumbbell /* disable VIP */ 340254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 341254885Sdumbbell /* enable the rom */ 342254885Sdumbbell WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 343254885Sdumbbell /* Disable VGA mode */ 344254885Sdumbbell WREG32(AVIVO_D1VGA_CONTROL, 345254885Sdumbbell (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 346254885Sdumbbell AVIVO_DVGA_CONTROL_TIMING_SELECT))); 347254885Sdumbbell WREG32(AVIVO_D2VGA_CONTROL, 348254885Sdumbbell (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 349254885Sdumbbell AVIVO_DVGA_CONTROL_TIMING_SELECT))); 350254885Sdumbbell WREG32(AVIVO_VGA_RENDER_CONTROL, 351254885Sdumbbell (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 352254885Sdumbbell 353254885Sdumbbell if (rdev->family == CHIP_RV730) { 354254885Sdumbbell cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL); 355254885Sdumbbell 356254885Sdumbbell /* enable bypass mode */ 357254885Sdumbbell WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | 358254885Sdumbbell R600_SPLL_BYPASS_EN)); 359254885Sdumbbell 360254885Sdumbbell /* wait for SPLL_CHG_STATUS to change to 1 */ 361254885Sdumbbell cg_spll_status = 0; 362254885Sdumbbell while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) 363254885Sdumbbell cg_spll_status = RREG32(R600_CG_SPLL_STATUS); 364254885Sdumbbell 365254885Sdumbbell WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); 366254885Sdumbbell } else 367254885Sdumbbell WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); 368254885Sdumbbell 369254885Sdumbbell r = radeon_read_bios(rdev); 370254885Sdumbbell 371254885Sdumbbell /* restore regs */ 372254885Sdumbbell if (rdev->family == CHIP_RV730) { 373254885Sdumbbell WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); 374254885Sdumbbell 375254885Sdumbbell /* wait for SPLL_CHG_STATUS to change to 1 */ 376254885Sdumbbell cg_spll_status = 0; 377254885Sdumbbell while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) 378254885Sdumbbell cg_spll_status = RREG32(R600_CG_SPLL_STATUS); 379254885Sdumbbell } 380254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, viph_control); 381254885Sdumbbell WREG32(R600_BUS_CNTL, bus_cntl); 382254885Sdumbbell WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 383254885Sdumbbell WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 384254885Sdumbbell WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 385254885Sdumbbell WREG32(R600_ROM_CNTL, rom_cntl); 386254885Sdumbbell return r; 387254885Sdumbbell} 388254885Sdumbbell 389254885Sdumbbellstatic bool r600_read_disabled_bios(struct radeon_device *rdev) 390254885Sdumbbell{ 391254885Sdumbbell uint32_t viph_control; 392254885Sdumbbell uint32_t bus_cntl; 393254885Sdumbbell uint32_t d1vga_control; 394254885Sdumbbell uint32_t d2vga_control; 395254885Sdumbbell uint32_t vga_render_control; 396254885Sdumbbell uint32_t rom_cntl; 397254885Sdumbbell uint32_t general_pwrmgt; 398254885Sdumbbell uint32_t low_vid_lower_gpio_cntl; 399254885Sdumbbell uint32_t medium_vid_lower_gpio_cntl; 400254885Sdumbbell uint32_t high_vid_lower_gpio_cntl; 401254885Sdumbbell uint32_t ctxsw_vid_lower_gpio_cntl; 402254885Sdumbbell uint32_t lower_gpio_enable; 403254885Sdumbbell bool r; 404254885Sdumbbell 405254885Sdumbbell DRM_INFO("%s: ===> Try disabled BIOS (r600)...\n", __func__); 406254885Sdumbbell 407254885Sdumbbell viph_control = RREG32(RADEON_VIPH_CONTROL); 408254885Sdumbbell bus_cntl = RREG32(R600_BUS_CNTL); 409254885Sdumbbell d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 410254885Sdumbbell d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 411254885Sdumbbell vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 412254885Sdumbbell rom_cntl = RREG32(R600_ROM_CNTL); 413254885Sdumbbell general_pwrmgt = RREG32(R600_GENERAL_PWRMGT); 414254885Sdumbbell low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL); 415254885Sdumbbell medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); 416254885Sdumbbell high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL); 417254885Sdumbbell ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL); 418254885Sdumbbell lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE); 419254885Sdumbbell 420254885Sdumbbell /* disable VIP */ 421254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 422254885Sdumbbell /* enable the rom */ 423254885Sdumbbell WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 424254885Sdumbbell /* Disable VGA mode */ 425254885Sdumbbell WREG32(AVIVO_D1VGA_CONTROL, 426254885Sdumbbell (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 427254885Sdumbbell AVIVO_DVGA_CONTROL_TIMING_SELECT))); 428254885Sdumbbell WREG32(AVIVO_D2VGA_CONTROL, 429254885Sdumbbell (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 430254885Sdumbbell AVIVO_DVGA_CONTROL_TIMING_SELECT))); 431254885Sdumbbell WREG32(AVIVO_VGA_RENDER_CONTROL, 432254885Sdumbbell (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 433254885Sdumbbell 434254885Sdumbbell WREG32(R600_ROM_CNTL, 435254885Sdumbbell ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | 436254885Sdumbbell (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | 437254885Sdumbbell R600_SCK_OVERWRITE)); 438254885Sdumbbell 439254885Sdumbbell WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); 440254885Sdumbbell WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, 441254885Sdumbbell (low_vid_lower_gpio_cntl & ~0x400)); 442254885Sdumbbell WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, 443254885Sdumbbell (medium_vid_lower_gpio_cntl & ~0x400)); 444254885Sdumbbell WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, 445254885Sdumbbell (high_vid_lower_gpio_cntl & ~0x400)); 446254885Sdumbbell WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, 447254885Sdumbbell (ctxsw_vid_lower_gpio_cntl & ~0x400)); 448254885Sdumbbell WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); 449254885Sdumbbell 450254885Sdumbbell r = radeon_read_bios(rdev); 451254885Sdumbbell 452254885Sdumbbell /* restore regs */ 453254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, viph_control); 454254885Sdumbbell WREG32(R600_BUS_CNTL, bus_cntl); 455254885Sdumbbell WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 456254885Sdumbbell WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 457254885Sdumbbell WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 458254885Sdumbbell WREG32(R600_ROM_CNTL, rom_cntl); 459254885Sdumbbell WREG32(R600_GENERAL_PWRMGT, general_pwrmgt); 460254885Sdumbbell WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); 461254885Sdumbbell WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); 462254885Sdumbbell WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); 463254885Sdumbbell WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); 464254885Sdumbbell WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); 465254885Sdumbbell return r; 466254885Sdumbbell} 467254885Sdumbbell 468254885Sdumbbellstatic bool avivo_read_disabled_bios(struct radeon_device *rdev) 469254885Sdumbbell{ 470254885Sdumbbell uint32_t seprom_cntl1; 471254885Sdumbbell uint32_t viph_control; 472254885Sdumbbell uint32_t bus_cntl; 473254885Sdumbbell uint32_t d1vga_control; 474254885Sdumbbell uint32_t d2vga_control; 475254885Sdumbbell uint32_t vga_render_control; 476254885Sdumbbell uint32_t gpiopad_a; 477254885Sdumbbell uint32_t gpiopad_en; 478254885Sdumbbell uint32_t gpiopad_mask; 479254885Sdumbbell bool r; 480254885Sdumbbell 481254885Sdumbbell DRM_INFO("%s: ===> Try disabled BIOS (avivo)...\n", __func__); 482254885Sdumbbell 483254885Sdumbbell seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); 484254885Sdumbbell viph_control = RREG32(RADEON_VIPH_CONTROL); 485254885Sdumbbell bus_cntl = RREG32(RV370_BUS_CNTL); 486254885Sdumbbell d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 487254885Sdumbbell d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 488254885Sdumbbell vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 489254885Sdumbbell gpiopad_a = RREG32(RADEON_GPIOPAD_A); 490254885Sdumbbell gpiopad_en = RREG32(RADEON_GPIOPAD_EN); 491254885Sdumbbell gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK); 492254885Sdumbbell 493254885Sdumbbell WREG32(RADEON_SEPROM_CNTL1, 494254885Sdumbbell ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 495254885Sdumbbell (0xc << RADEON_SCK_PRESCALE_SHIFT))); 496254885Sdumbbell WREG32(RADEON_GPIOPAD_A, 0); 497254885Sdumbbell WREG32(RADEON_GPIOPAD_EN, 0); 498254885Sdumbbell WREG32(RADEON_GPIOPAD_MASK, 0); 499254885Sdumbbell 500254885Sdumbbell /* disable VIP */ 501254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 502254885Sdumbbell 503254885Sdumbbell /* enable the rom */ 504254885Sdumbbell WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); 505254885Sdumbbell 506254885Sdumbbell /* Disable VGA mode */ 507254885Sdumbbell WREG32(AVIVO_D1VGA_CONTROL, 508254885Sdumbbell (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 509254885Sdumbbell AVIVO_DVGA_CONTROL_TIMING_SELECT))); 510254885Sdumbbell WREG32(AVIVO_D2VGA_CONTROL, 511254885Sdumbbell (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 512254885Sdumbbell AVIVO_DVGA_CONTROL_TIMING_SELECT))); 513254885Sdumbbell WREG32(AVIVO_VGA_RENDER_CONTROL, 514254885Sdumbbell (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 515254885Sdumbbell 516254885Sdumbbell r = radeon_read_bios(rdev); 517254885Sdumbbell 518254885Sdumbbell /* restore regs */ 519254885Sdumbbell WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); 520254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, viph_control); 521254885Sdumbbell WREG32(RV370_BUS_CNTL, bus_cntl); 522254885Sdumbbell WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 523254885Sdumbbell WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 524254885Sdumbbell WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 525254885Sdumbbell WREG32(RADEON_GPIOPAD_A, gpiopad_a); 526254885Sdumbbell WREG32(RADEON_GPIOPAD_EN, gpiopad_en); 527254885Sdumbbell WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask); 528254885Sdumbbell return r; 529254885Sdumbbell} 530254885Sdumbbell 531254885Sdumbbellstatic bool legacy_read_disabled_bios(struct radeon_device *rdev) 532254885Sdumbbell{ 533254885Sdumbbell uint32_t seprom_cntl1; 534254885Sdumbbell uint32_t viph_control; 535254885Sdumbbell uint32_t bus_cntl; 536254885Sdumbbell uint32_t crtc_gen_cntl; 537254885Sdumbbell uint32_t crtc2_gen_cntl; 538254885Sdumbbell uint32_t crtc_ext_cntl; 539254885Sdumbbell uint32_t fp2_gen_cntl; 540254885Sdumbbell bool r; 541254885Sdumbbell 542254885Sdumbbell DRM_INFO("%s: ===> Try disabled BIOS (legacy)...\n", __func__); 543254885Sdumbbell 544254885Sdumbbell seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); 545254885Sdumbbell viph_control = RREG32(RADEON_VIPH_CONTROL); 546254885Sdumbbell if (rdev->flags & RADEON_IS_PCIE) 547254885Sdumbbell bus_cntl = RREG32(RV370_BUS_CNTL); 548254885Sdumbbell else 549254885Sdumbbell bus_cntl = RREG32(RADEON_BUS_CNTL); 550254885Sdumbbell crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 551254885Sdumbbell crtc2_gen_cntl = 0; 552254885Sdumbbell crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 553254885Sdumbbell fp2_gen_cntl = 0; 554254885Sdumbbell 555254885Sdumbbell#define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 556254885Sdumbbell 557254885Sdumbbell if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { 558254885Sdumbbell fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 559254885Sdumbbell } 560254885Sdumbbell 561254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 562254885Sdumbbell crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 563254885Sdumbbell } 564254885Sdumbbell 565254885Sdumbbell WREG32(RADEON_SEPROM_CNTL1, 566254885Sdumbbell ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 567254885Sdumbbell (0xc << RADEON_SCK_PRESCALE_SHIFT))); 568254885Sdumbbell 569254885Sdumbbell /* disable VIP */ 570254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 571254885Sdumbbell 572254885Sdumbbell /* enable the rom */ 573254885Sdumbbell if (rdev->flags & RADEON_IS_PCIE) 574254885Sdumbbell WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); 575254885Sdumbbell else 576254885Sdumbbell WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 577254885Sdumbbell 578254885Sdumbbell /* Turn off mem requests and CRTC for both controllers */ 579254885Sdumbbell WREG32(RADEON_CRTC_GEN_CNTL, 580254885Sdumbbell ((crtc_gen_cntl & ~RADEON_CRTC_EN) | 581254885Sdumbbell (RADEON_CRTC_DISP_REQ_EN_B | 582254885Sdumbbell RADEON_CRTC_EXT_DISP_EN))); 583254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 584254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, 585254885Sdumbbell ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | 586254885Sdumbbell RADEON_CRTC2_DISP_REQ_EN_B)); 587254885Sdumbbell } 588254885Sdumbbell /* Turn off CRTC */ 589254885Sdumbbell WREG32(RADEON_CRTC_EXT_CNTL, 590254885Sdumbbell ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | 591254885Sdumbbell (RADEON_CRTC_SYNC_TRISTAT | 592254885Sdumbbell RADEON_CRTC_DISPLAY_DIS))); 593254885Sdumbbell 594254885Sdumbbell if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { 595254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); 596254885Sdumbbell } 597254885Sdumbbell 598254885Sdumbbell r = radeon_read_bios(rdev); 599254885Sdumbbell 600254885Sdumbbell /* restore regs */ 601254885Sdumbbell WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); 602254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, viph_control); 603254885Sdumbbell if (rdev->flags & RADEON_IS_PCIE) 604254885Sdumbbell WREG32(RV370_BUS_CNTL, bus_cntl); 605254885Sdumbbell else 606254885Sdumbbell WREG32(RADEON_BUS_CNTL, bus_cntl); 607254885Sdumbbell WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); 608254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 609254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 610254885Sdumbbell } 611254885Sdumbbell WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 612254885Sdumbbell if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { 613254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 614254885Sdumbbell } 615254885Sdumbbell return r; 616254885Sdumbbell} 617254885Sdumbbell 618254885Sdumbbellstatic bool radeon_read_disabled_bios(struct radeon_device *rdev) 619254885Sdumbbell{ 620254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) 621254885Sdumbbell return igp_read_bios_from_vram(rdev); 622254885Sdumbbell else if (rdev->family >= CHIP_BARTS) 623254885Sdumbbell return ni_read_disabled_bios(rdev); 624254885Sdumbbell else if (rdev->family >= CHIP_RV770) 625254885Sdumbbell return r700_read_disabled_bios(rdev); 626254885Sdumbbell else if (rdev->family >= CHIP_R600) 627254885Sdumbbell return r600_read_disabled_bios(rdev); 628254885Sdumbbell else if (rdev->family >= CHIP_RS600) 629254885Sdumbbell return avivo_read_disabled_bios(rdev); 630254885Sdumbbell else 631254885Sdumbbell return legacy_read_disabled_bios(rdev); 632254885Sdumbbell} 633254885Sdumbbell 634282199Sdumbbell#ifdef CONFIG_ACPI 635254885Sdumbbellstatic bool radeon_acpi_vfct_bios(struct radeon_device *rdev) 636254885Sdumbbell{ 637254885Sdumbbell bool ret = false; 638254885Sdumbbell ACPI_TABLE_HEADER *hdr; 639254885Sdumbbell ACPI_SIZE tbl_size; 640254885Sdumbbell UEFI_ACPI_VFCT *vfct; 641254885Sdumbbell GOP_VBIOS_CONTENT *vbios; 642254885Sdumbbell VFCT_IMAGE_HEADER *vhdr; 643254885Sdumbbell ACPI_STATUS status; 644254885Sdumbbell 645254885Sdumbbell DRM_INFO("%s: ===> Try VFCT...\n", __func__); 646254885Sdumbbell 647254885Sdumbbell DRM_INFO("%s: Get \"VFCT\" ACPI table\n", __func__); 648254885Sdumbbell status = AcpiGetTable("VFCT", 1, &hdr); 649254885Sdumbbell if (!ACPI_SUCCESS(status)) { 650254885Sdumbbell DRM_INFO("%s: Failed to get \"VFCT\" table: %s\n", 651254885Sdumbbell __func__, AcpiFormatException(status)); 652254885Sdumbbell return false; 653254885Sdumbbell } 654254885Sdumbbell tbl_size = hdr->Length; 655254885Sdumbbell if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { 656254885Sdumbbell DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); 657254885Sdumbbell goto out_unmap; 658254885Sdumbbell } 659254885Sdumbbell 660254885Sdumbbell vfct = (UEFI_ACPI_VFCT *)hdr; 661254885Sdumbbell if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { 662254885Sdumbbell DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); 663254885Sdumbbell goto out_unmap; 664254885Sdumbbell } 665254885Sdumbbell 666254885Sdumbbell vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); 667254885Sdumbbell vhdr = &vbios->VbiosHeader; 668254885Sdumbbell DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", 669254885Sdumbbell vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, 670254885Sdumbbell vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); 671254885Sdumbbell 672254885Sdumbbell if (vhdr->PCIBus != rdev->ddev->pci_bus || 673254885Sdumbbell vhdr->PCIDevice != rdev->ddev->pci_slot || 674254885Sdumbbell vhdr->PCIFunction != rdev->ddev->pci_func || 675254885Sdumbbell vhdr->VendorID != rdev->ddev->pci_vendor || 676254885Sdumbbell vhdr->DeviceID != rdev->ddev->pci_device) { 677254885Sdumbbell DRM_INFO("ACPI VFCT table is not for this card\n"); 678254885Sdumbbell goto out_unmap; 679254885Sdumbbell }; 680254885Sdumbbell 681254885Sdumbbell if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { 682254885Sdumbbell DRM_ERROR("ACPI VFCT image truncated\n"); 683254885Sdumbbell goto out_unmap; 684254885Sdumbbell } 685254885Sdumbbell 686282199Sdumbbell rdev->bios = malloc(vhdr->ImageLength, DRM_MEM_DRIVER, M_NOWAIT); 687282199Sdumbbell if (rdev->bios) 688282199Sdumbbell memcpy(rdev->bios, &vbios->VbiosContent, vhdr->ImageLength); 689254885Sdumbbell ret = !!rdev->bios; 690254885Sdumbbell 691254885Sdumbbellout_unmap: 692254885Sdumbbell return ret; 693254885Sdumbbell} 694282199Sdumbbell#else 695282199Sdumbbellstatic inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) 696282199Sdumbbell{ 697282199Sdumbbell return false; 698282199Sdumbbell} 699282199Sdumbbell#endif 700254885Sdumbbell 701254885Sdumbbellbool radeon_get_bios(struct radeon_device *rdev) 702254885Sdumbbell{ 703254885Sdumbbell bool r; 704254885Sdumbbell uint16_t tmp; 705254885Sdumbbell 706254885Sdumbbell r = radeon_atrm_get_bios(rdev); 707254885Sdumbbell if (r == false) 708254885Sdumbbell r = radeon_acpi_vfct_bios(rdev); 709254885Sdumbbell if (r == false) 710254885Sdumbbell r = igp_read_bios_from_vram(rdev); 711254885Sdumbbell if (r == false) 712254885Sdumbbell r = radeon_read_bios(rdev); 713254885Sdumbbell if (r == false) { 714254885Sdumbbell r = radeon_read_disabled_bios(rdev); 715254885Sdumbbell } 716254885Sdumbbell if (r == false || rdev->bios == NULL) { 717254885Sdumbbell DRM_ERROR("Unable to locate a BIOS ROM\n"); 718254885Sdumbbell rdev->bios = NULL; 719254885Sdumbbell return false; 720254885Sdumbbell } 721254885Sdumbbell if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { 722254885Sdumbbell DRM_ERROR("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]); 723254885Sdumbbell goto free_bios; 724254885Sdumbbell } 725254885Sdumbbell 726254885Sdumbbell tmp = RBIOS16(0x18); 727254885Sdumbbell if (RBIOS8(tmp + 0x14) != 0x0) { 728254885Sdumbbell DRM_INFO("Not an x86 BIOS ROM, not using.\n"); 729254885Sdumbbell goto free_bios; 730254885Sdumbbell } 731254885Sdumbbell 732254885Sdumbbell rdev->bios_header_start = RBIOS16(0x48); 733254885Sdumbbell if (!rdev->bios_header_start) { 734254885Sdumbbell goto free_bios; 735254885Sdumbbell } 736254885Sdumbbell tmp = rdev->bios_header_start + 4; 737254885Sdumbbell if (!memcmp(rdev->bios + tmp, "ATOM", 4) || 738254885Sdumbbell !memcmp(rdev->bios + tmp, "MOTA", 4)) { 739254885Sdumbbell rdev->is_atom_bios = true; 740254885Sdumbbell } else { 741254885Sdumbbell rdev->is_atom_bios = false; 742254885Sdumbbell } 743254885Sdumbbell 744254885Sdumbbell DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); 745254885Sdumbbell return true; 746254885Sdumbbellfree_bios: 747254885Sdumbbell free(rdev->bios, DRM_MEM_DRIVER); 748254885Sdumbbell rdev->bios = NULL; 749254885Sdumbbell return false; 750254885Sdumbbell} 751