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