18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc. 48c2ecf20Sopenharmony_ci * Copyright 2009 Jerome Glisse. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Authors: Dave Airlie 258c2ecf20Sopenharmony_ci * Alex Deucher 268c2ecf20Sopenharmony_ci * Jerome Glisse 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <linux/acpi.h> 308c2ecf20Sopenharmony_ci#include <linux/pci.h> 318c2ecf20Sopenharmony_ci#include <linux/slab.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include <drm/drm_device.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include "atom.h" 368c2ecf20Sopenharmony_ci#include "radeon.h" 378c2ecf20Sopenharmony_ci#include "radeon_reg.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* 408c2ecf20Sopenharmony_ci * BIOS. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* If you boot an IGP board with a discrete card as the primary, 448c2ecf20Sopenharmony_ci * the IGP rom is not accessible via the rom bar as the IGP rom is 458c2ecf20Sopenharmony_ci * part of the system bios. On boot, the system bios puts a 468c2ecf20Sopenharmony_ci * copy of the igp rom at the start of vram if a discrete card is 478c2ecf20Sopenharmony_ci * present. 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_cistatic bool igp_read_bios_from_vram(struct radeon_device *rdev) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci uint8_t __iomem *bios; 528c2ecf20Sopenharmony_ci resource_size_t vram_base; 538c2ecf20Sopenharmony_ci resource_size_t size = 256 * 1024; /* ??? */ 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_IS_IGP)) 568c2ecf20Sopenharmony_ci if (!radeon_card_posted(rdev)) 578c2ecf20Sopenharmony_ci return false; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci rdev->bios = NULL; 608c2ecf20Sopenharmony_ci vram_base = pci_resource_start(rdev->pdev, 0); 618c2ecf20Sopenharmony_ci bios = ioremap(vram_base, size); 628c2ecf20Sopenharmony_ci if (!bios) { 638c2ecf20Sopenharmony_ci return false; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { 678c2ecf20Sopenharmony_ci iounmap(bios); 688c2ecf20Sopenharmony_ci return false; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci rdev->bios = kmalloc(size, GFP_KERNEL); 718c2ecf20Sopenharmony_ci if (rdev->bios == NULL) { 728c2ecf20Sopenharmony_ci iounmap(bios); 738c2ecf20Sopenharmony_ci return false; 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci memcpy_fromio(rdev->bios, bios, size); 768c2ecf20Sopenharmony_ci iounmap(bios); 778c2ecf20Sopenharmony_ci return true; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic bool radeon_read_bios(struct radeon_device *rdev) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci uint8_t __iomem *bios, val1, val2; 838c2ecf20Sopenharmony_ci size_t size; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci rdev->bios = NULL; 868c2ecf20Sopenharmony_ci /* XXX: some cards may return 0 for rom size? ddx has a workaround */ 878c2ecf20Sopenharmony_ci bios = pci_map_rom(rdev->pdev, &size); 888c2ecf20Sopenharmony_ci if (!bios) { 898c2ecf20Sopenharmony_ci return false; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci val1 = readb(&bios[0]); 938c2ecf20Sopenharmony_ci val2 = readb(&bios[1]); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (size == 0 || val1 != 0x55 || val2 != 0xaa) { 968c2ecf20Sopenharmony_ci pci_unmap_rom(rdev->pdev, bios); 978c2ecf20Sopenharmony_ci return false; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci rdev->bios = kzalloc(size, GFP_KERNEL); 1008c2ecf20Sopenharmony_ci if (rdev->bios == NULL) { 1018c2ecf20Sopenharmony_ci pci_unmap_rom(rdev->pdev, bios); 1028c2ecf20Sopenharmony_ci return false; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci memcpy_fromio(rdev->bios, bios, size); 1058c2ecf20Sopenharmony_ci pci_unmap_rom(rdev->pdev, bios); 1068c2ecf20Sopenharmony_ci return true; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic bool radeon_read_platform_bios(struct radeon_device *rdev) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci phys_addr_t rom = rdev->pdev->rom; 1128c2ecf20Sopenharmony_ci size_t romlen = rdev->pdev->romlen; 1138c2ecf20Sopenharmony_ci void __iomem *bios; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci rdev->bios = NULL; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci if (!rom || romlen == 0) 1188c2ecf20Sopenharmony_ci return false; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci rdev->bios = kzalloc(romlen, GFP_KERNEL); 1218c2ecf20Sopenharmony_ci if (!rdev->bios) 1228c2ecf20Sopenharmony_ci return false; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci bios = ioremap(rom, romlen); 1258c2ecf20Sopenharmony_ci if (!bios) 1268c2ecf20Sopenharmony_ci goto free_bios; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci memcpy_fromio(rdev->bios, bios, romlen); 1298c2ecf20Sopenharmony_ci iounmap(bios); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) 1328c2ecf20Sopenharmony_ci goto free_bios; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci return true; 1358c2ecf20Sopenharmony_cifree_bios: 1368c2ecf20Sopenharmony_ci kfree(rdev->bios); 1378c2ecf20Sopenharmony_ci return false; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI 1418c2ecf20Sopenharmony_ci/* ATRM is used to get the BIOS on the discrete cards in 1428c2ecf20Sopenharmony_ci * dual-gpu systems. 1438c2ecf20Sopenharmony_ci */ 1448c2ecf20Sopenharmony_ci/* retrieve the ROM in 4k blocks */ 1458c2ecf20Sopenharmony_ci#define ATRM_BIOS_PAGE 4096 1468c2ecf20Sopenharmony_ci/** 1478c2ecf20Sopenharmony_ci * radeon_atrm_call - fetch a chunk of the vbios 1488c2ecf20Sopenharmony_ci * 1498c2ecf20Sopenharmony_ci * @atrm_handle: acpi ATRM handle 1508c2ecf20Sopenharmony_ci * @bios: vbios image pointer 1518c2ecf20Sopenharmony_ci * @offset: offset of vbios image data to fetch 1528c2ecf20Sopenharmony_ci * @len: length of vbios image data to fetch 1538c2ecf20Sopenharmony_ci * 1548c2ecf20Sopenharmony_ci * Executes ATRM to fetch a chunk of the discrete 1558c2ecf20Sopenharmony_ci * vbios image on PX systems (all asics). 1568c2ecf20Sopenharmony_ci * Returns the length of the buffer fetched. 1578c2ecf20Sopenharmony_ci */ 1588c2ecf20Sopenharmony_cistatic int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, 1598c2ecf20Sopenharmony_ci int offset, int len) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci acpi_status status; 1628c2ecf20Sopenharmony_ci union acpi_object atrm_arg_elements[2], *obj; 1638c2ecf20Sopenharmony_ci struct acpi_object_list atrm_arg; 1648c2ecf20Sopenharmony_ci struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci atrm_arg.count = 2; 1678c2ecf20Sopenharmony_ci atrm_arg.pointer = &atrm_arg_elements[0]; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; 1708c2ecf20Sopenharmony_ci atrm_arg_elements[0].integer.value = offset; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; 1738c2ecf20Sopenharmony_ci atrm_arg_elements[1].integer.value = len; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); 1768c2ecf20Sopenharmony_ci if (ACPI_FAILURE(status)) { 1778c2ecf20Sopenharmony_ci printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); 1788c2ecf20Sopenharmony_ci return -ENODEV; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci obj = (union acpi_object *)buffer.pointer; 1828c2ecf20Sopenharmony_ci memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); 1838c2ecf20Sopenharmony_ci len = obj->buffer.length; 1848c2ecf20Sopenharmony_ci kfree(buffer.pointer); 1858c2ecf20Sopenharmony_ci return len; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic bool radeon_atrm_get_bios(struct radeon_device *rdev) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci int ret; 1918c2ecf20Sopenharmony_ci int size = 256 * 1024; 1928c2ecf20Sopenharmony_ci int i; 1938c2ecf20Sopenharmony_ci struct pci_dev *pdev = NULL; 1948c2ecf20Sopenharmony_ci acpi_handle dhandle, atrm_handle; 1958c2ecf20Sopenharmony_ci acpi_status status; 1968c2ecf20Sopenharmony_ci bool found = false; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* ATRM is for the discrete card only */ 1998c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 2008c2ecf20Sopenharmony_ci return false; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { 2038c2ecf20Sopenharmony_ci dhandle = ACPI_HANDLE(&pdev->dev); 2048c2ecf20Sopenharmony_ci if (!dhandle) 2058c2ecf20Sopenharmony_ci continue; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); 2088c2ecf20Sopenharmony_ci if (!ACPI_FAILURE(status)) { 2098c2ecf20Sopenharmony_ci found = true; 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (!found) { 2158c2ecf20Sopenharmony_ci while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { 2168c2ecf20Sopenharmony_ci dhandle = ACPI_HANDLE(&pdev->dev); 2178c2ecf20Sopenharmony_ci if (!dhandle) 2188c2ecf20Sopenharmony_ci continue; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); 2218c2ecf20Sopenharmony_ci if (!ACPI_FAILURE(status)) { 2228c2ecf20Sopenharmony_ci found = true; 2238c2ecf20Sopenharmony_ci break; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (!found) 2298c2ecf20Sopenharmony_ci return false; 2308c2ecf20Sopenharmony_ci pci_dev_put(pdev); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci rdev->bios = kmalloc(size, GFP_KERNEL); 2338c2ecf20Sopenharmony_ci if (!rdev->bios) { 2348c2ecf20Sopenharmony_ci DRM_ERROR("Unable to allocate bios\n"); 2358c2ecf20Sopenharmony_ci return false; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { 2398c2ecf20Sopenharmony_ci ret = radeon_atrm_call(atrm_handle, 2408c2ecf20Sopenharmony_ci rdev->bios, 2418c2ecf20Sopenharmony_ci (i * ATRM_BIOS_PAGE), 2428c2ecf20Sopenharmony_ci ATRM_BIOS_PAGE); 2438c2ecf20Sopenharmony_ci if (ret < ATRM_BIOS_PAGE) 2448c2ecf20Sopenharmony_ci break; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { 2488c2ecf20Sopenharmony_ci kfree(rdev->bios); 2498c2ecf20Sopenharmony_ci return false; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci return true; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci#else 2548c2ecf20Sopenharmony_cistatic inline bool radeon_atrm_get_bios(struct radeon_device *rdev) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci return false; 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci#endif 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic bool ni_read_disabled_bios(struct radeon_device *rdev) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci u32 bus_cntl; 2638c2ecf20Sopenharmony_ci u32 d1vga_control; 2648c2ecf20Sopenharmony_ci u32 d2vga_control; 2658c2ecf20Sopenharmony_ci u32 vga_render_control; 2668c2ecf20Sopenharmony_ci u32 rom_cntl; 2678c2ecf20Sopenharmony_ci bool r; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci bus_cntl = RREG32(R600_BUS_CNTL); 2708c2ecf20Sopenharmony_ci d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 2718c2ecf20Sopenharmony_ci d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 2728c2ecf20Sopenharmony_ci vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 2738c2ecf20Sopenharmony_ci rom_cntl = RREG32(R600_ROM_CNTL); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* enable the rom */ 2768c2ecf20Sopenharmony_ci WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 2778c2ecf20Sopenharmony_ci if (!ASIC_IS_NODCE(rdev)) { 2788c2ecf20Sopenharmony_ci /* Disable VGA mode */ 2798c2ecf20Sopenharmony_ci WREG32(AVIVO_D1VGA_CONTROL, 2808c2ecf20Sopenharmony_ci (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 2818c2ecf20Sopenharmony_ci AVIVO_DVGA_CONTROL_TIMING_SELECT))); 2828c2ecf20Sopenharmony_ci WREG32(AVIVO_D2VGA_CONTROL, 2838c2ecf20Sopenharmony_ci (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 2848c2ecf20Sopenharmony_ci AVIVO_DVGA_CONTROL_TIMING_SELECT))); 2858c2ecf20Sopenharmony_ci WREG32(AVIVO_VGA_RENDER_CONTROL, 2868c2ecf20Sopenharmony_ci (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci r = radeon_read_bios(rdev); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* restore regs */ 2938c2ecf20Sopenharmony_ci WREG32(R600_BUS_CNTL, bus_cntl); 2948c2ecf20Sopenharmony_ci if (!ASIC_IS_NODCE(rdev)) { 2958c2ecf20Sopenharmony_ci WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 2968c2ecf20Sopenharmony_ci WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 2978c2ecf20Sopenharmony_ci WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci WREG32(R600_ROM_CNTL, rom_cntl); 3008c2ecf20Sopenharmony_ci return r; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic bool r700_read_disabled_bios(struct radeon_device *rdev) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci uint32_t viph_control; 3068c2ecf20Sopenharmony_ci uint32_t bus_cntl; 3078c2ecf20Sopenharmony_ci uint32_t d1vga_control; 3088c2ecf20Sopenharmony_ci uint32_t d2vga_control; 3098c2ecf20Sopenharmony_ci uint32_t vga_render_control; 3108c2ecf20Sopenharmony_ci uint32_t rom_cntl; 3118c2ecf20Sopenharmony_ci uint32_t cg_spll_func_cntl = 0; 3128c2ecf20Sopenharmony_ci uint32_t cg_spll_status; 3138c2ecf20Sopenharmony_ci bool r; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci viph_control = RREG32(RADEON_VIPH_CONTROL); 3168c2ecf20Sopenharmony_ci bus_cntl = RREG32(R600_BUS_CNTL); 3178c2ecf20Sopenharmony_ci d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 3188c2ecf20Sopenharmony_ci d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 3198c2ecf20Sopenharmony_ci vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 3208c2ecf20Sopenharmony_ci rom_cntl = RREG32(R600_ROM_CNTL); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* disable VIP */ 3238c2ecf20Sopenharmony_ci WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 3248c2ecf20Sopenharmony_ci /* enable the rom */ 3258c2ecf20Sopenharmony_ci WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 3268c2ecf20Sopenharmony_ci /* Disable VGA mode */ 3278c2ecf20Sopenharmony_ci WREG32(AVIVO_D1VGA_CONTROL, 3288c2ecf20Sopenharmony_ci (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 3298c2ecf20Sopenharmony_ci AVIVO_DVGA_CONTROL_TIMING_SELECT))); 3308c2ecf20Sopenharmony_ci WREG32(AVIVO_D2VGA_CONTROL, 3318c2ecf20Sopenharmony_ci (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 3328c2ecf20Sopenharmony_ci AVIVO_DVGA_CONTROL_TIMING_SELECT))); 3338c2ecf20Sopenharmony_ci WREG32(AVIVO_VGA_RENDER_CONTROL, 3348c2ecf20Sopenharmony_ci (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RV730) { 3378c2ecf20Sopenharmony_ci cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* enable bypass mode */ 3408c2ecf20Sopenharmony_ci WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | 3418c2ecf20Sopenharmony_ci R600_SPLL_BYPASS_EN)); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* wait for SPLL_CHG_STATUS to change to 1 */ 3448c2ecf20Sopenharmony_ci cg_spll_status = 0; 3458c2ecf20Sopenharmony_ci while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) 3468c2ecf20Sopenharmony_ci cg_spll_status = RREG32(R600_CG_SPLL_STATUS); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); 3498c2ecf20Sopenharmony_ci } else 3508c2ecf20Sopenharmony_ci WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci r = radeon_read_bios(rdev); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci /* restore regs */ 3558c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RV730) { 3568c2ecf20Sopenharmony_ci WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* wait for SPLL_CHG_STATUS to change to 1 */ 3598c2ecf20Sopenharmony_ci cg_spll_status = 0; 3608c2ecf20Sopenharmony_ci while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) 3618c2ecf20Sopenharmony_ci cg_spll_status = RREG32(R600_CG_SPLL_STATUS); 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci WREG32(RADEON_VIPH_CONTROL, viph_control); 3648c2ecf20Sopenharmony_ci WREG32(R600_BUS_CNTL, bus_cntl); 3658c2ecf20Sopenharmony_ci WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 3668c2ecf20Sopenharmony_ci WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 3678c2ecf20Sopenharmony_ci WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 3688c2ecf20Sopenharmony_ci WREG32(R600_ROM_CNTL, rom_cntl); 3698c2ecf20Sopenharmony_ci return r; 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic bool r600_read_disabled_bios(struct radeon_device *rdev) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci uint32_t viph_control; 3758c2ecf20Sopenharmony_ci uint32_t bus_cntl; 3768c2ecf20Sopenharmony_ci uint32_t d1vga_control; 3778c2ecf20Sopenharmony_ci uint32_t d2vga_control; 3788c2ecf20Sopenharmony_ci uint32_t vga_render_control; 3798c2ecf20Sopenharmony_ci uint32_t rom_cntl; 3808c2ecf20Sopenharmony_ci uint32_t general_pwrmgt; 3818c2ecf20Sopenharmony_ci uint32_t low_vid_lower_gpio_cntl; 3828c2ecf20Sopenharmony_ci uint32_t medium_vid_lower_gpio_cntl; 3838c2ecf20Sopenharmony_ci uint32_t high_vid_lower_gpio_cntl; 3848c2ecf20Sopenharmony_ci uint32_t ctxsw_vid_lower_gpio_cntl; 3858c2ecf20Sopenharmony_ci uint32_t lower_gpio_enable; 3868c2ecf20Sopenharmony_ci bool r; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci viph_control = RREG32(RADEON_VIPH_CONTROL); 3898c2ecf20Sopenharmony_ci bus_cntl = RREG32(R600_BUS_CNTL); 3908c2ecf20Sopenharmony_ci d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 3918c2ecf20Sopenharmony_ci d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 3928c2ecf20Sopenharmony_ci vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 3938c2ecf20Sopenharmony_ci rom_cntl = RREG32(R600_ROM_CNTL); 3948c2ecf20Sopenharmony_ci general_pwrmgt = RREG32(R600_GENERAL_PWRMGT); 3958c2ecf20Sopenharmony_ci low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL); 3968c2ecf20Sopenharmony_ci medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); 3978c2ecf20Sopenharmony_ci high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL); 3988c2ecf20Sopenharmony_ci ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL); 3998c2ecf20Sopenharmony_ci lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* disable VIP */ 4028c2ecf20Sopenharmony_ci WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 4038c2ecf20Sopenharmony_ci /* enable the rom */ 4048c2ecf20Sopenharmony_ci WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); 4058c2ecf20Sopenharmony_ci /* Disable VGA mode */ 4068c2ecf20Sopenharmony_ci WREG32(AVIVO_D1VGA_CONTROL, 4078c2ecf20Sopenharmony_ci (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 4088c2ecf20Sopenharmony_ci AVIVO_DVGA_CONTROL_TIMING_SELECT))); 4098c2ecf20Sopenharmony_ci WREG32(AVIVO_D2VGA_CONTROL, 4108c2ecf20Sopenharmony_ci (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 4118c2ecf20Sopenharmony_ci AVIVO_DVGA_CONTROL_TIMING_SELECT))); 4128c2ecf20Sopenharmony_ci WREG32(AVIVO_VGA_RENDER_CONTROL, 4138c2ecf20Sopenharmony_ci (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci WREG32(R600_ROM_CNTL, 4168c2ecf20Sopenharmony_ci ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | 4178c2ecf20Sopenharmony_ci (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | 4188c2ecf20Sopenharmony_ci R600_SCK_OVERWRITE)); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); 4218c2ecf20Sopenharmony_ci WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, 4228c2ecf20Sopenharmony_ci (low_vid_lower_gpio_cntl & ~0x400)); 4238c2ecf20Sopenharmony_ci WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, 4248c2ecf20Sopenharmony_ci (medium_vid_lower_gpio_cntl & ~0x400)); 4258c2ecf20Sopenharmony_ci WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, 4268c2ecf20Sopenharmony_ci (high_vid_lower_gpio_cntl & ~0x400)); 4278c2ecf20Sopenharmony_ci WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, 4288c2ecf20Sopenharmony_ci (ctxsw_vid_lower_gpio_cntl & ~0x400)); 4298c2ecf20Sopenharmony_ci WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci r = radeon_read_bios(rdev); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* restore regs */ 4348c2ecf20Sopenharmony_ci WREG32(RADEON_VIPH_CONTROL, viph_control); 4358c2ecf20Sopenharmony_ci WREG32(R600_BUS_CNTL, bus_cntl); 4368c2ecf20Sopenharmony_ci WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 4378c2ecf20Sopenharmony_ci WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 4388c2ecf20Sopenharmony_ci WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 4398c2ecf20Sopenharmony_ci WREG32(R600_ROM_CNTL, rom_cntl); 4408c2ecf20Sopenharmony_ci WREG32(R600_GENERAL_PWRMGT, general_pwrmgt); 4418c2ecf20Sopenharmony_ci WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); 4428c2ecf20Sopenharmony_ci WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); 4438c2ecf20Sopenharmony_ci WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); 4448c2ecf20Sopenharmony_ci WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); 4458c2ecf20Sopenharmony_ci WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); 4468c2ecf20Sopenharmony_ci return r; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_cistatic bool avivo_read_disabled_bios(struct radeon_device *rdev) 4508c2ecf20Sopenharmony_ci{ 4518c2ecf20Sopenharmony_ci uint32_t seprom_cntl1; 4528c2ecf20Sopenharmony_ci uint32_t viph_control; 4538c2ecf20Sopenharmony_ci uint32_t bus_cntl; 4548c2ecf20Sopenharmony_ci uint32_t d1vga_control; 4558c2ecf20Sopenharmony_ci uint32_t d2vga_control; 4568c2ecf20Sopenharmony_ci uint32_t vga_render_control; 4578c2ecf20Sopenharmony_ci uint32_t gpiopad_a; 4588c2ecf20Sopenharmony_ci uint32_t gpiopad_en; 4598c2ecf20Sopenharmony_ci uint32_t gpiopad_mask; 4608c2ecf20Sopenharmony_ci bool r; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); 4638c2ecf20Sopenharmony_ci viph_control = RREG32(RADEON_VIPH_CONTROL); 4648c2ecf20Sopenharmony_ci bus_cntl = RREG32(RV370_BUS_CNTL); 4658c2ecf20Sopenharmony_ci d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); 4668c2ecf20Sopenharmony_ci d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); 4678c2ecf20Sopenharmony_ci vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); 4688c2ecf20Sopenharmony_ci gpiopad_a = RREG32(RADEON_GPIOPAD_A); 4698c2ecf20Sopenharmony_ci gpiopad_en = RREG32(RADEON_GPIOPAD_EN); 4708c2ecf20Sopenharmony_ci gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci WREG32(RADEON_SEPROM_CNTL1, 4738c2ecf20Sopenharmony_ci ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 4748c2ecf20Sopenharmony_ci (0xc << RADEON_SCK_PRESCALE_SHIFT))); 4758c2ecf20Sopenharmony_ci WREG32(RADEON_GPIOPAD_A, 0); 4768c2ecf20Sopenharmony_ci WREG32(RADEON_GPIOPAD_EN, 0); 4778c2ecf20Sopenharmony_ci WREG32(RADEON_GPIOPAD_MASK, 0); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci /* disable VIP */ 4808c2ecf20Sopenharmony_ci WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* enable the rom */ 4838c2ecf20Sopenharmony_ci WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* Disable VGA mode */ 4868c2ecf20Sopenharmony_ci WREG32(AVIVO_D1VGA_CONTROL, 4878c2ecf20Sopenharmony_ci (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 4888c2ecf20Sopenharmony_ci AVIVO_DVGA_CONTROL_TIMING_SELECT))); 4898c2ecf20Sopenharmony_ci WREG32(AVIVO_D2VGA_CONTROL, 4908c2ecf20Sopenharmony_ci (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 4918c2ecf20Sopenharmony_ci AVIVO_DVGA_CONTROL_TIMING_SELECT))); 4928c2ecf20Sopenharmony_ci WREG32(AVIVO_VGA_RENDER_CONTROL, 4938c2ecf20Sopenharmony_ci (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci r = radeon_read_bios(rdev); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci /* restore regs */ 4988c2ecf20Sopenharmony_ci WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); 4998c2ecf20Sopenharmony_ci WREG32(RADEON_VIPH_CONTROL, viph_control); 5008c2ecf20Sopenharmony_ci WREG32(RV370_BUS_CNTL, bus_cntl); 5018c2ecf20Sopenharmony_ci WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); 5028c2ecf20Sopenharmony_ci WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); 5038c2ecf20Sopenharmony_ci WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 5048c2ecf20Sopenharmony_ci WREG32(RADEON_GPIOPAD_A, gpiopad_a); 5058c2ecf20Sopenharmony_ci WREG32(RADEON_GPIOPAD_EN, gpiopad_en); 5068c2ecf20Sopenharmony_ci WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask); 5078c2ecf20Sopenharmony_ci return r; 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic bool legacy_read_disabled_bios(struct radeon_device *rdev) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci uint32_t seprom_cntl1; 5138c2ecf20Sopenharmony_ci uint32_t viph_control; 5148c2ecf20Sopenharmony_ci uint32_t bus_cntl; 5158c2ecf20Sopenharmony_ci uint32_t crtc_gen_cntl; 5168c2ecf20Sopenharmony_ci uint32_t crtc2_gen_cntl; 5178c2ecf20Sopenharmony_ci uint32_t crtc_ext_cntl; 5188c2ecf20Sopenharmony_ci uint32_t fp2_gen_cntl; 5198c2ecf20Sopenharmony_ci bool r; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); 5228c2ecf20Sopenharmony_ci viph_control = RREG32(RADEON_VIPH_CONTROL); 5238c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 5248c2ecf20Sopenharmony_ci bus_cntl = RREG32(RV370_BUS_CNTL); 5258c2ecf20Sopenharmony_ci else 5268c2ecf20Sopenharmony_ci bus_cntl = RREG32(RADEON_BUS_CNTL); 5278c2ecf20Sopenharmony_ci crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 5288c2ecf20Sopenharmony_ci crtc2_gen_cntl = 0; 5298c2ecf20Sopenharmony_ci crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 5308c2ecf20Sopenharmony_ci fp2_gen_cntl = 0; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { 5338c2ecf20Sopenharmony_ci fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 5378c2ecf20Sopenharmony_ci crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci WREG32(RADEON_SEPROM_CNTL1, 5418c2ecf20Sopenharmony_ci ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 5428c2ecf20Sopenharmony_ci (0xc << RADEON_SCK_PRESCALE_SHIFT))); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /* disable VIP */ 5458c2ecf20Sopenharmony_ci WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci /* enable the rom */ 5488c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 5498c2ecf20Sopenharmony_ci WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); 5508c2ecf20Sopenharmony_ci else 5518c2ecf20Sopenharmony_ci WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci /* Turn off mem requests and CRTC for both controllers */ 5548c2ecf20Sopenharmony_ci WREG32(RADEON_CRTC_GEN_CNTL, 5558c2ecf20Sopenharmony_ci ((crtc_gen_cntl & ~RADEON_CRTC_EN) | 5568c2ecf20Sopenharmony_ci (RADEON_CRTC_DISP_REQ_EN_B | 5578c2ecf20Sopenharmony_ci RADEON_CRTC_EXT_DISP_EN))); 5588c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 5598c2ecf20Sopenharmony_ci WREG32(RADEON_CRTC2_GEN_CNTL, 5608c2ecf20Sopenharmony_ci ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | 5618c2ecf20Sopenharmony_ci RADEON_CRTC2_DISP_REQ_EN_B)); 5628c2ecf20Sopenharmony_ci } 5638c2ecf20Sopenharmony_ci /* Turn off CRTC */ 5648c2ecf20Sopenharmony_ci WREG32(RADEON_CRTC_EXT_CNTL, 5658c2ecf20Sopenharmony_ci ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | 5668c2ecf20Sopenharmony_ci (RADEON_CRTC_SYNC_TRISTAT | 5678c2ecf20Sopenharmony_ci RADEON_CRTC_DISPLAY_DIS))); 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { 5708c2ecf20Sopenharmony_ci WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci r = radeon_read_bios(rdev); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci /* restore regs */ 5768c2ecf20Sopenharmony_ci WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); 5778c2ecf20Sopenharmony_ci WREG32(RADEON_VIPH_CONTROL, viph_control); 5788c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 5798c2ecf20Sopenharmony_ci WREG32(RV370_BUS_CNTL, bus_cntl); 5808c2ecf20Sopenharmony_ci else 5818c2ecf20Sopenharmony_ci WREG32(RADEON_BUS_CNTL, bus_cntl); 5828c2ecf20Sopenharmony_ci WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); 5838c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 5848c2ecf20Sopenharmony_ci WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 5858c2ecf20Sopenharmony_ci } 5868c2ecf20Sopenharmony_ci WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 5878c2ecf20Sopenharmony_ci if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { 5888c2ecf20Sopenharmony_ci WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci return r; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic bool radeon_read_disabled_bios(struct radeon_device *rdev) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 5968c2ecf20Sopenharmony_ci return igp_read_bios_from_vram(rdev); 5978c2ecf20Sopenharmony_ci else if (rdev->family >= CHIP_BARTS) 5988c2ecf20Sopenharmony_ci return ni_read_disabled_bios(rdev); 5998c2ecf20Sopenharmony_ci else if (rdev->family >= CHIP_RV770) 6008c2ecf20Sopenharmony_ci return r700_read_disabled_bios(rdev); 6018c2ecf20Sopenharmony_ci else if (rdev->family >= CHIP_R600) 6028c2ecf20Sopenharmony_ci return r600_read_disabled_bios(rdev); 6038c2ecf20Sopenharmony_ci else if (rdev->family >= CHIP_RS600) 6048c2ecf20Sopenharmony_ci return avivo_read_disabled_bios(rdev); 6058c2ecf20Sopenharmony_ci else 6068c2ecf20Sopenharmony_ci return legacy_read_disabled_bios(rdev); 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI 6108c2ecf20Sopenharmony_cistatic bool radeon_acpi_vfct_bios(struct radeon_device *rdev) 6118c2ecf20Sopenharmony_ci{ 6128c2ecf20Sopenharmony_ci struct acpi_table_header *hdr; 6138c2ecf20Sopenharmony_ci acpi_size tbl_size; 6148c2ecf20Sopenharmony_ci UEFI_ACPI_VFCT *vfct; 6158c2ecf20Sopenharmony_ci unsigned offset; 6168c2ecf20Sopenharmony_ci bool r = false; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) 6198c2ecf20Sopenharmony_ci return false; 6208c2ecf20Sopenharmony_ci tbl_size = hdr->length; 6218c2ecf20Sopenharmony_ci if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { 6228c2ecf20Sopenharmony_ci DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); 6238c2ecf20Sopenharmony_ci goto out; 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci vfct = (UEFI_ACPI_VFCT *)hdr; 6278c2ecf20Sopenharmony_ci offset = vfct->VBIOSImageOffset; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci while (offset < tbl_size) { 6308c2ecf20Sopenharmony_ci GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset); 6318c2ecf20Sopenharmony_ci VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci offset += sizeof(VFCT_IMAGE_HEADER); 6348c2ecf20Sopenharmony_ci if (offset > tbl_size) { 6358c2ecf20Sopenharmony_ci DRM_ERROR("ACPI VFCT image header truncated\n"); 6368c2ecf20Sopenharmony_ci goto out; 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci offset += vhdr->ImageLength; 6408c2ecf20Sopenharmony_ci if (offset > tbl_size) { 6418c2ecf20Sopenharmony_ci DRM_ERROR("ACPI VFCT image truncated\n"); 6428c2ecf20Sopenharmony_ci goto out; 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci if (vhdr->ImageLength && 6468c2ecf20Sopenharmony_ci vhdr->PCIBus == rdev->pdev->bus->number && 6478c2ecf20Sopenharmony_ci vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) && 6488c2ecf20Sopenharmony_ci vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) && 6498c2ecf20Sopenharmony_ci vhdr->VendorID == rdev->pdev->vendor && 6508c2ecf20Sopenharmony_ci vhdr->DeviceID == rdev->pdev->device) { 6518c2ecf20Sopenharmony_ci rdev->bios = kmemdup(&vbios->VbiosContent, 6528c2ecf20Sopenharmony_ci vhdr->ImageLength, 6538c2ecf20Sopenharmony_ci GFP_KERNEL); 6548c2ecf20Sopenharmony_ci if (rdev->bios) 6558c2ecf20Sopenharmony_ci r = true; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci goto out; 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ciout: 6648c2ecf20Sopenharmony_ci acpi_put_table(hdr); 6658c2ecf20Sopenharmony_ci return r; 6668c2ecf20Sopenharmony_ci} 6678c2ecf20Sopenharmony_ci#else 6688c2ecf20Sopenharmony_cistatic inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci return false; 6718c2ecf20Sopenharmony_ci} 6728c2ecf20Sopenharmony_ci#endif 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_cibool radeon_get_bios(struct radeon_device *rdev) 6758c2ecf20Sopenharmony_ci{ 6768c2ecf20Sopenharmony_ci bool r; 6778c2ecf20Sopenharmony_ci uint16_t tmp; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci r = radeon_atrm_get_bios(rdev); 6808c2ecf20Sopenharmony_ci if (!r) 6818c2ecf20Sopenharmony_ci r = radeon_acpi_vfct_bios(rdev); 6828c2ecf20Sopenharmony_ci if (!r) 6838c2ecf20Sopenharmony_ci r = igp_read_bios_from_vram(rdev); 6848c2ecf20Sopenharmony_ci if (!r) 6858c2ecf20Sopenharmony_ci r = radeon_read_bios(rdev); 6868c2ecf20Sopenharmony_ci if (!r) 6878c2ecf20Sopenharmony_ci r = radeon_read_disabled_bios(rdev); 6888c2ecf20Sopenharmony_ci if (!r) 6898c2ecf20Sopenharmony_ci r = radeon_read_platform_bios(rdev); 6908c2ecf20Sopenharmony_ci if (!r || rdev->bios == NULL) { 6918c2ecf20Sopenharmony_ci DRM_ERROR("Unable to locate a BIOS ROM\n"); 6928c2ecf20Sopenharmony_ci rdev->bios = NULL; 6938c2ecf20Sopenharmony_ci return false; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { 6968c2ecf20Sopenharmony_ci printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]); 6978c2ecf20Sopenharmony_ci goto free_bios; 6988c2ecf20Sopenharmony_ci } 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci tmp = RBIOS16(0x18); 7018c2ecf20Sopenharmony_ci if (RBIOS8(tmp + 0x14) != 0x0) { 7028c2ecf20Sopenharmony_ci DRM_INFO("Not an x86 BIOS ROM, not using.\n"); 7038c2ecf20Sopenharmony_ci goto free_bios; 7048c2ecf20Sopenharmony_ci } 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci rdev->bios_header_start = RBIOS16(0x48); 7078c2ecf20Sopenharmony_ci if (!rdev->bios_header_start) { 7088c2ecf20Sopenharmony_ci goto free_bios; 7098c2ecf20Sopenharmony_ci } 7108c2ecf20Sopenharmony_ci tmp = rdev->bios_header_start + 4; 7118c2ecf20Sopenharmony_ci if (!memcmp(rdev->bios + tmp, "ATOM", 4) || 7128c2ecf20Sopenharmony_ci !memcmp(rdev->bios + tmp, "MOTA", 4)) { 7138c2ecf20Sopenharmony_ci rdev->is_atom_bios = true; 7148c2ecf20Sopenharmony_ci } else { 7158c2ecf20Sopenharmony_ci rdev->is_atom_bios = false; 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); 7198c2ecf20Sopenharmony_ci return true; 7208c2ecf20Sopenharmony_cifree_bios: 7218c2ecf20Sopenharmony_ci kfree(rdev->bios); 7228c2ecf20Sopenharmony_ci rdev->bios = NULL; 7238c2ecf20Sopenharmony_ci return false; 7248c2ecf20Sopenharmony_ci} 725