1926deccbSFrançois Tigeot /*
2926deccbSFrançois Tigeot * Copyright 2008 Advanced Micro Devices, Inc.
3926deccbSFrançois Tigeot * Copyright 2008 Red Hat Inc.
4926deccbSFrançois Tigeot * Copyright 2009 Jerome Glisse.
5926deccbSFrançois Tigeot *
6926deccbSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a
7926deccbSFrançois Tigeot * copy of this software and associated documentation files (the "Software"),
8926deccbSFrançois Tigeot * to deal in the Software without restriction, including without limitation
9926deccbSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10926deccbSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the
11926deccbSFrançois Tigeot * Software is furnished to do so, subject to the following conditions:
12926deccbSFrançois Tigeot *
13926deccbSFrançois Tigeot * The above copyright notice and this permission notice shall be included in
14926deccbSFrançois Tigeot * all copies or substantial portions of the Software.
15926deccbSFrançois Tigeot *
16926deccbSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17926deccbSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18926deccbSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19926deccbSFrançois Tigeot * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20926deccbSFrançois Tigeot * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21926deccbSFrançois Tigeot * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22926deccbSFrançois Tigeot * OTHER DEALINGS IN THE SOFTWARE.
23926deccbSFrançois Tigeot *
24926deccbSFrançois Tigeot * Authors: Dave Airlie
25926deccbSFrançois Tigeot * Alex Deucher
26926deccbSFrançois Tigeot * Jerome Glisse
27926deccbSFrançois Tigeot *
28926deccbSFrançois Tigeot * $FreeBSD: head/sys/dev/drm2/radeon/radeon_bios.c 255572 2013-09-14 17:22:34Z dumbbell $
29926deccbSFrançois Tigeot */
30926deccbSFrançois Tigeot
31926deccbSFrançois Tigeot #include <drm/drmP.h>
32926deccbSFrançois Tigeot #include "radeon_reg.h"
33926deccbSFrançois Tigeot #include "radeon.h"
34926deccbSFrançois Tigeot #include "atom.h"
35926deccbSFrançois Tigeot
36c4ef309bSzrj #include <linux/slab.h>
37926deccbSFrançois Tigeot /*
38926deccbSFrançois Tigeot * BIOS.
39926deccbSFrançois Tigeot */
40926deccbSFrançois Tigeot
41926deccbSFrançois Tigeot /* If you boot an IGP board with a discrete card as the primary,
42926deccbSFrançois Tigeot * the IGP rom is not accessible via the rom bar as the IGP rom is
43926deccbSFrançois Tigeot * part of the system bios. On boot, the system bios puts a
44926deccbSFrançois Tigeot * copy of the igp rom at the start of vram if a discrete card is
45926deccbSFrançois Tigeot * present.
46926deccbSFrançois Tigeot */
igp_read_bios_from_vram(struct radeon_device * rdev)47926deccbSFrançois Tigeot static bool igp_read_bios_from_vram(struct radeon_device *rdev)
48926deccbSFrançois Tigeot {
49926deccbSFrançois Tigeot uint8_t __iomem *bios;
50926deccbSFrançois Tigeot resource_size_t vram_base;
51926deccbSFrançois Tigeot resource_size_t size = 256 * 1024; /* ??? */
52926deccbSFrançois Tigeot
53926deccbSFrançois Tigeot if (!(rdev->flags & RADEON_IS_IGP))
546431cd91SFrançois Tigeot if (!radeon_card_posted(rdev))
55926deccbSFrançois Tigeot return false;
56926deccbSFrançois Tigeot
57926deccbSFrançois Tigeot rdev->bios = NULL;
584a26d795SImre Vadasz vram_base = pci_resource_start(rdev->pdev, 0);
596431cd91SFrançois Tigeot bios = ioremap(vram_base, size);
606431cd91SFrançois Tigeot if (!bios) {
61926deccbSFrançois Tigeot return false;
62926deccbSFrançois Tigeot }
63926deccbSFrançois Tigeot
64926deccbSFrançois Tigeot if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
6524409b39SFrançois Tigeot iounmap(bios);
66926deccbSFrançois Tigeot return false;
67926deccbSFrançois Tigeot }
685a3b77d5SFrançois Tigeot rdev->bios = kmalloc(size, M_DRM, M_WAITOK);
69926deccbSFrançois Tigeot if (rdev->bios == NULL) {
7024409b39SFrançois Tigeot iounmap(bios);
71926deccbSFrançois Tigeot return false;
72926deccbSFrançois Tigeot }
73926deccbSFrançois Tigeot memcpy_fromio(rdev->bios, bios, size);
7424409b39SFrançois Tigeot iounmap(bios);
75926deccbSFrançois Tigeot return true;
76926deccbSFrançois Tigeot }
77926deccbSFrançois Tigeot
radeon_read_bios(struct radeon_device * rdev)78926deccbSFrançois Tigeot static bool radeon_read_bios(struct radeon_device *rdev)
79926deccbSFrançois Tigeot {
807dcf36dcSFrançois Tigeot uint8_t __iomem *bios, val1, val2;
81926deccbSFrançois Tigeot size_t size;
827dcf36dcSFrançois Tigeot device_t vga_dev = device_get_parent(rdev->dev->bsddev);
83926deccbSFrançois Tigeot
84926deccbSFrançois Tigeot rdev->bios = NULL;
85926deccbSFrançois Tigeot /* XXX: some cards may return 0 for rom size? ddx has a workaround */
86926deccbSFrançois Tigeot bios = vga_pci_map_bios(vga_dev, &size);
87926deccbSFrançois Tigeot if (!bios) {
88926deccbSFrançois Tigeot return false;
89926deccbSFrançois Tigeot }
90926deccbSFrançois Tigeot
917dcf36dcSFrançois Tigeot val1 = readb(&bios[0]);
927dcf36dcSFrançois Tigeot val2 = readb(&bios[1]);
937dcf36dcSFrançois Tigeot
947dcf36dcSFrançois Tigeot if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
95926deccbSFrançois Tigeot vga_pci_unmap_bios(vga_dev, bios);
967112e8c7Sdumbbell return false;
97926deccbSFrançois Tigeot }
987dcf36dcSFrançois Tigeot rdev->bios = kzalloc(size, GFP_KERNEL);
997dcf36dcSFrançois Tigeot if (rdev->bios == NULL) {
1007dcf36dcSFrançois Tigeot vga_pci_unmap_bios(vga_dev, bios);
1017dcf36dcSFrançois Tigeot return false;
1027dcf36dcSFrançois Tigeot }
1037dcf36dcSFrançois Tigeot memcpy_fromio(rdev->bios, bios, size);
104926deccbSFrançois Tigeot vga_pci_unmap_bios(vga_dev, bios);
105926deccbSFrançois Tigeot return true;
106926deccbSFrançois Tigeot }
107926deccbSFrançois Tigeot
radeon_read_platform_bios(struct radeon_device * rdev)108b403bed8SMichael Neumann static bool radeon_read_platform_bios(struct radeon_device *rdev)
109b403bed8SMichael Neumann {
110b403bed8SMichael Neumann uint8_t __iomem *bios;
111b403bed8SMichael Neumann size_t size;
112b403bed8SMichael Neumann
113b403bed8SMichael Neumann rdev->bios = NULL;
114b403bed8SMichael Neumann
115b403bed8SMichael Neumann #if 0
116b403bed8SMichael Neumann // XXX: FIXME
117b403bed8SMichael Neumann bios = pci_platform_rom(rdev->pdev, &size);
118b403bed8SMichael Neumann #else
119b403bed8SMichael Neumann size = 0;
120b403bed8SMichael Neumann bios = NULL;
121b403bed8SMichael Neumann #endif
122b403bed8SMichael Neumann if (!bios) {
123b403bed8SMichael Neumann return false;
124b403bed8SMichael Neumann }
125b403bed8SMichael Neumann
126b403bed8SMichael Neumann if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
127b403bed8SMichael Neumann return false;
128b403bed8SMichael Neumann }
1297dcf36dcSFrançois Tigeot rdev->bios = kmemdup(bios, size, GFP_KERNEL);
130b403bed8SMichael Neumann if (rdev->bios == NULL) {
131b403bed8SMichael Neumann return false;
132b403bed8SMichael Neumann }
1337dcf36dcSFrançois Tigeot
134b403bed8SMichael Neumann return true;
135b403bed8SMichael Neumann }
136b403bed8SMichael Neumann
137452a88ebSzrj #ifdef CONFIG_ACPI
138926deccbSFrançois Tigeot /* ATRM is used to get the BIOS on the discrete cards in
139926deccbSFrançois Tigeot * dual-gpu systems.
140926deccbSFrançois Tigeot */
141926deccbSFrançois Tigeot /* retrieve the ROM in 4k blocks */
142926deccbSFrançois Tigeot #define ATRM_BIOS_PAGE 4096
143926deccbSFrançois Tigeot /**
144926deccbSFrançois Tigeot * radeon_atrm_call - fetch a chunk of the vbios
145926deccbSFrançois Tigeot *
146926deccbSFrançois Tigeot * @atrm_handle: acpi ATRM handle
147926deccbSFrançois Tigeot * @bios: vbios image pointer
148926deccbSFrançois Tigeot * @offset: offset of vbios image data to fetch
149926deccbSFrançois Tigeot * @len: length of vbios image data to fetch
150926deccbSFrançois Tigeot *
151926deccbSFrançois Tigeot * Executes ATRM to fetch a chunk of the discrete
152926deccbSFrançois Tigeot * vbios image on PX systems (all asics).
153926deccbSFrançois Tigeot * Returns the length of the buffer fetched.
154926deccbSFrançois Tigeot */
radeon_atrm_call(ACPI_HANDLE atrm_handle,uint8_t * bios,int offset,int len)155926deccbSFrançois Tigeot static int radeon_atrm_call(ACPI_HANDLE atrm_handle, uint8_t *bios,
156926deccbSFrançois Tigeot int offset, int len)
157926deccbSFrançois Tigeot {
158926deccbSFrançois Tigeot ACPI_STATUS status;
159926deccbSFrançois Tigeot ACPI_OBJECT atrm_arg_elements[2], *obj;
160926deccbSFrançois Tigeot ACPI_OBJECT_LIST atrm_arg;
161926deccbSFrançois Tigeot ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL};
162926deccbSFrançois Tigeot
163926deccbSFrançois Tigeot atrm_arg.Count = 2;
164926deccbSFrançois Tigeot atrm_arg.Pointer = &atrm_arg_elements[0];
165926deccbSFrançois Tigeot
166926deccbSFrançois Tigeot atrm_arg_elements[0].Type = ACPI_TYPE_INTEGER;
167926deccbSFrançois Tigeot atrm_arg_elements[0].Integer.Value = offset;
168926deccbSFrançois Tigeot
169926deccbSFrançois Tigeot atrm_arg_elements[1].Type = ACPI_TYPE_INTEGER;
170926deccbSFrançois Tigeot atrm_arg_elements[1].Integer.Value = len;
171926deccbSFrançois Tigeot
172926deccbSFrançois Tigeot status = AcpiEvaluateObject(atrm_handle, NULL, &atrm_arg, &buffer);
173926deccbSFrançois Tigeot if (ACPI_FAILURE(status)) {
174c4ef309bSzrj printk("failed to evaluate ATRM got %s\n", AcpiFormatException(status));
175926deccbSFrançois Tigeot return -ENODEV;
176926deccbSFrançois Tigeot }
177926deccbSFrançois Tigeot
178926deccbSFrançois Tigeot obj = (ACPI_OBJECT *)buffer.Pointer;
179926deccbSFrançois Tigeot memcpy(bios+offset, obj->Buffer.Pointer, obj->Buffer.Length);
180926deccbSFrançois Tigeot len = obj->Buffer.Length;
181926deccbSFrançois Tigeot AcpiOsFree(buffer.Pointer);
182926deccbSFrançois Tigeot return len;
183926deccbSFrançois Tigeot }
184926deccbSFrançois Tigeot
radeon_atrm_get_bios(struct radeon_device * rdev)185926deccbSFrançois Tigeot static bool radeon_atrm_get_bios(struct radeon_device *rdev)
186926deccbSFrançois Tigeot {
187926deccbSFrançois Tigeot int ret;
188926deccbSFrançois Tigeot int size = 256 * 1024;
189926deccbSFrançois Tigeot int i;
190926deccbSFrançois Tigeot device_t dev;
191926deccbSFrançois Tigeot ACPI_HANDLE dhandle, atrm_handle;
192926deccbSFrançois Tigeot ACPI_STATUS status;
193926deccbSFrançois Tigeot bool found = false;
194926deccbSFrançois Tigeot
195926deccbSFrançois Tigeot DRM_INFO("%s: ===> Try ATRM...\n", __func__);
196926deccbSFrançois Tigeot
197926deccbSFrançois Tigeot /* ATRM is for the discrete card only */
198926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_IGP) {
199926deccbSFrançois Tigeot DRM_INFO("%s: IGP card detected, skipping this method...\n",
200926deccbSFrançois Tigeot __func__);
201926deccbSFrançois Tigeot return false;
202926deccbSFrançois Tigeot }
203926deccbSFrançois Tigeot
204926deccbSFrançois Tigeot #ifdef DUMBBELL_WIP
205926deccbSFrançois Tigeot while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
206926deccbSFrançois Tigeot #endif /* DUMBBELL_WIP */
207926deccbSFrançois Tigeot if ((dev = pci_find_class(PCIC_DISPLAY, PCIS_DISPLAY_VGA)) != NULL) {
208926deccbSFrançois Tigeot DRM_INFO("%s: pci_find_class() found: %d:%d:%d:%d, vendor=%04x, device=%04x\n",
209926deccbSFrançois Tigeot __func__,
210926deccbSFrançois Tigeot pci_get_domain(dev),
211926deccbSFrançois Tigeot pci_get_bus(dev),
212926deccbSFrançois Tigeot pci_get_slot(dev),
213926deccbSFrançois Tigeot pci_get_function(dev),
214926deccbSFrançois Tigeot pci_get_vendor(dev),
215926deccbSFrançois Tigeot pci_get_device(dev));
216926deccbSFrançois Tigeot DRM_INFO("%s: Get ACPI device handle\n", __func__);
217926deccbSFrançois Tigeot dhandle = acpi_get_handle(dev);
218926deccbSFrançois Tigeot #ifdef DUMBBELL_WIP
219926deccbSFrançois Tigeot if (!dhandle)
220926deccbSFrançois Tigeot continue;
221926deccbSFrançois Tigeot #endif /* DUMBBELL_WIP */
222926deccbSFrançois Tigeot if (!dhandle)
223926deccbSFrançois Tigeot return false;
224926deccbSFrançois Tigeot
225926deccbSFrançois Tigeot DRM_INFO("%s: Get ACPI handle for \"ATRM\"\n", __func__);
226926deccbSFrançois Tigeot status = AcpiGetHandle(dhandle, "ATRM", &atrm_handle);
227926deccbSFrançois Tigeot if (!ACPI_FAILURE(status)) {
228926deccbSFrançois Tigeot found = true;
229926deccbSFrançois Tigeot #ifdef DUMBBELL_WIP
230926deccbSFrançois Tigeot break;
231926deccbSFrançois Tigeot #endif /* DUMBBELL_WIP */
232926deccbSFrançois Tigeot } else {
233926deccbSFrançois Tigeot DRM_INFO("%s: Failed to get \"ATRM\" handle: %s\n",
234926deccbSFrançois Tigeot __func__, AcpiFormatException(status));
235926deccbSFrançois Tigeot }
236926deccbSFrançois Tigeot }
237926deccbSFrançois Tigeot
238926deccbSFrançois Tigeot if (!found)
239926deccbSFrançois Tigeot return false;
240926deccbSFrançois Tigeot
2415a3b77d5SFrançois Tigeot rdev->bios = kmalloc(size, M_DRM, M_WAITOK);
242926deccbSFrançois Tigeot if (!rdev->bios) {
243926deccbSFrançois Tigeot DRM_ERROR("Unable to allocate bios\n");
244926deccbSFrançois Tigeot return false;
245926deccbSFrançois Tigeot }
246926deccbSFrançois Tigeot
247926deccbSFrançois Tigeot for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
248926deccbSFrançois Tigeot DRM_INFO("%s: Call radeon_atrm_call()\n", __func__);
249926deccbSFrançois Tigeot ret = radeon_atrm_call(atrm_handle,
250926deccbSFrançois Tigeot rdev->bios,
251926deccbSFrançois Tigeot (i * ATRM_BIOS_PAGE),
252926deccbSFrançois Tigeot ATRM_BIOS_PAGE);
253926deccbSFrançois Tigeot if (ret < ATRM_BIOS_PAGE)
254926deccbSFrançois Tigeot break;
255926deccbSFrançois Tigeot }
256926deccbSFrançois Tigeot
257926deccbSFrançois Tigeot if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
258926deccbSFrançois Tigeot if (i == 0) {
259926deccbSFrançois Tigeot DRM_INFO("%s: Incorrect BIOS size\n", __func__);
260926deccbSFrançois Tigeot } else {
261926deccbSFrançois Tigeot DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n",
262926deccbSFrançois Tigeot __func__, rdev->bios[0], rdev->bios[1]);
263926deccbSFrançois Tigeot }
264c4ef309bSzrj kfree(rdev->bios);
265926deccbSFrançois Tigeot return false;
266926deccbSFrançois Tigeot }
267926deccbSFrançois Tigeot return true;
268926deccbSFrançois Tigeot }
269452a88ebSzrj #else
270452a88ebSzrj static inline bool radeon_atrm_get_bios(struct radeon_device *rdev)
271452a88ebSzrj {
272452a88ebSzrj return false;
273452a88ebSzrj }
274452a88ebSzrj #endif
275926deccbSFrançois Tigeot
276926deccbSFrançois Tigeot static bool ni_read_disabled_bios(struct radeon_device *rdev)
277926deccbSFrançois Tigeot {
278926deccbSFrançois Tigeot u32 bus_cntl;
279926deccbSFrançois Tigeot u32 d1vga_control;
280926deccbSFrançois Tigeot u32 d2vga_control;
281926deccbSFrançois Tigeot u32 vga_render_control;
282926deccbSFrançois Tigeot u32 rom_cntl;
283926deccbSFrançois Tigeot bool r;
284926deccbSFrançois Tigeot
285926deccbSFrançois Tigeot DRM_INFO("%s: ===> Try disabled BIOS (ni)...\n", __func__);
286926deccbSFrançois Tigeot
287926deccbSFrançois Tigeot bus_cntl = RREG32(R600_BUS_CNTL);
288926deccbSFrançois Tigeot d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
289926deccbSFrançois Tigeot d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
290926deccbSFrançois Tigeot vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
291926deccbSFrançois Tigeot rom_cntl = RREG32(R600_ROM_CNTL);
292926deccbSFrançois Tigeot
293926deccbSFrançois Tigeot /* enable the rom */
294926deccbSFrançois Tigeot WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
295f43cf1b1SMichael Neumann if (!ASIC_IS_NODCE(rdev)) {
296926deccbSFrançois Tigeot /* Disable VGA mode */
297926deccbSFrançois Tigeot WREG32(AVIVO_D1VGA_CONTROL,
298926deccbSFrançois Tigeot (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
299926deccbSFrançois Tigeot AVIVO_DVGA_CONTROL_TIMING_SELECT)));
300926deccbSFrançois Tigeot WREG32(AVIVO_D2VGA_CONTROL,
301926deccbSFrançois Tigeot (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
302926deccbSFrançois Tigeot AVIVO_DVGA_CONTROL_TIMING_SELECT)));
303926deccbSFrançois Tigeot WREG32(AVIVO_VGA_RENDER_CONTROL,
304926deccbSFrançois Tigeot (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
305f43cf1b1SMichael Neumann }
306926deccbSFrançois Tigeot WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE);
307926deccbSFrançois Tigeot
308926deccbSFrançois Tigeot r = radeon_read_bios(rdev);
309926deccbSFrançois Tigeot
310926deccbSFrançois Tigeot /* restore regs */
311926deccbSFrançois Tigeot WREG32(R600_BUS_CNTL, bus_cntl);
312f43cf1b1SMichael Neumann if (!ASIC_IS_NODCE(rdev)) {
313926deccbSFrançois Tigeot WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
314926deccbSFrançois Tigeot WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
315926deccbSFrançois Tigeot WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
316f43cf1b1SMichael Neumann }
317926deccbSFrançois Tigeot WREG32(R600_ROM_CNTL, rom_cntl);
318926deccbSFrançois Tigeot return r;
319926deccbSFrançois Tigeot }
320926deccbSFrançois Tigeot
321926deccbSFrançois Tigeot static bool r700_read_disabled_bios(struct radeon_device *rdev)
322926deccbSFrançois Tigeot {
323926deccbSFrançois Tigeot uint32_t viph_control;
324926deccbSFrançois Tigeot uint32_t bus_cntl;
325926deccbSFrançois Tigeot uint32_t d1vga_control;
326926deccbSFrançois Tigeot uint32_t d2vga_control;
327926deccbSFrançois Tigeot uint32_t vga_render_control;
328926deccbSFrançois Tigeot uint32_t rom_cntl;
329926deccbSFrançois Tigeot uint32_t cg_spll_func_cntl = 0;
330926deccbSFrançois Tigeot uint32_t cg_spll_status;
331926deccbSFrançois Tigeot bool r;
332926deccbSFrançois Tigeot
333926deccbSFrançois Tigeot DRM_INFO("%s: ===> Try disabled BIOS (r700)...\n", __func__);
334926deccbSFrançois Tigeot
335926deccbSFrançois Tigeot viph_control = RREG32(RADEON_VIPH_CONTROL);
336926deccbSFrançois Tigeot bus_cntl = RREG32(R600_BUS_CNTL);
337926deccbSFrançois Tigeot d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
338926deccbSFrançois Tigeot d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
339926deccbSFrançois Tigeot vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
340926deccbSFrançois Tigeot rom_cntl = RREG32(R600_ROM_CNTL);
341926deccbSFrançois Tigeot
342926deccbSFrançois Tigeot /* disable VIP */
343926deccbSFrançois Tigeot WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
344926deccbSFrançois Tigeot /* enable the rom */
345926deccbSFrançois Tigeot WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
346926deccbSFrançois Tigeot /* Disable VGA mode */
347926deccbSFrançois Tigeot WREG32(AVIVO_D1VGA_CONTROL,
348926deccbSFrançois Tigeot (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
349926deccbSFrançois Tigeot AVIVO_DVGA_CONTROL_TIMING_SELECT)));
350926deccbSFrançois Tigeot WREG32(AVIVO_D2VGA_CONTROL,
351926deccbSFrançois Tigeot (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
352926deccbSFrançois Tigeot AVIVO_DVGA_CONTROL_TIMING_SELECT)));
353926deccbSFrançois Tigeot WREG32(AVIVO_VGA_RENDER_CONTROL,
354926deccbSFrançois Tigeot (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
355926deccbSFrançois Tigeot
356926deccbSFrançois Tigeot if (rdev->family == CHIP_RV730) {
357926deccbSFrançois Tigeot cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL);
358926deccbSFrançois Tigeot
359926deccbSFrançois Tigeot /* enable bypass mode */
360926deccbSFrançois Tigeot WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl |
361926deccbSFrançois Tigeot R600_SPLL_BYPASS_EN));
362926deccbSFrançois Tigeot
363926deccbSFrançois Tigeot /* wait for SPLL_CHG_STATUS to change to 1 */
364926deccbSFrançois Tigeot cg_spll_status = 0;
365926deccbSFrançois Tigeot while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
366926deccbSFrançois Tigeot cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
367926deccbSFrançois Tigeot
368926deccbSFrançois Tigeot WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE));
369926deccbSFrançois Tigeot } else
370926deccbSFrançois Tigeot WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE));
371926deccbSFrançois Tigeot
372926deccbSFrançois Tigeot r = radeon_read_bios(rdev);
373926deccbSFrançois Tigeot
374926deccbSFrançois Tigeot /* restore regs */
375926deccbSFrançois Tigeot if (rdev->family == CHIP_RV730) {
376926deccbSFrançois Tigeot WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl);
377926deccbSFrançois Tigeot
378926deccbSFrançois Tigeot /* wait for SPLL_CHG_STATUS to change to 1 */
379926deccbSFrançois Tigeot cg_spll_status = 0;
380926deccbSFrançois Tigeot while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
381926deccbSFrançois Tigeot cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
382926deccbSFrançois Tigeot }
383926deccbSFrançois Tigeot WREG32(RADEON_VIPH_CONTROL, viph_control);
384926deccbSFrançois Tigeot WREG32(R600_BUS_CNTL, bus_cntl);
385926deccbSFrançois Tigeot WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
386926deccbSFrançois Tigeot WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
387926deccbSFrançois Tigeot WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
388926deccbSFrançois Tigeot WREG32(R600_ROM_CNTL, rom_cntl);
389926deccbSFrançois Tigeot return r;
390926deccbSFrançois Tigeot }
391926deccbSFrançois Tigeot
392926deccbSFrançois Tigeot static bool r600_read_disabled_bios(struct radeon_device *rdev)
393926deccbSFrançois Tigeot {
394926deccbSFrançois Tigeot uint32_t viph_control;
395926deccbSFrançois Tigeot uint32_t bus_cntl;
396926deccbSFrançois Tigeot uint32_t d1vga_control;
397926deccbSFrançois Tigeot uint32_t d2vga_control;
398926deccbSFrançois Tigeot uint32_t vga_render_control;
399926deccbSFrançois Tigeot uint32_t rom_cntl;
400926deccbSFrançois Tigeot uint32_t general_pwrmgt;
401926deccbSFrançois Tigeot uint32_t low_vid_lower_gpio_cntl;
402926deccbSFrançois Tigeot uint32_t medium_vid_lower_gpio_cntl;
403926deccbSFrançois Tigeot uint32_t high_vid_lower_gpio_cntl;
404926deccbSFrançois Tigeot uint32_t ctxsw_vid_lower_gpio_cntl;
405926deccbSFrançois Tigeot uint32_t lower_gpio_enable;
406926deccbSFrançois Tigeot bool r;
407926deccbSFrançois Tigeot
408926deccbSFrançois Tigeot DRM_INFO("%s: ===> Try disabled BIOS (r600)...\n", __func__);
409926deccbSFrançois Tigeot
410926deccbSFrançois Tigeot viph_control = RREG32(RADEON_VIPH_CONTROL);
411926deccbSFrançois Tigeot bus_cntl = RREG32(R600_BUS_CNTL);
412926deccbSFrançois Tigeot d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
413926deccbSFrançois Tigeot d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
414926deccbSFrançois Tigeot vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
415926deccbSFrançois Tigeot rom_cntl = RREG32(R600_ROM_CNTL);
416926deccbSFrançois Tigeot general_pwrmgt = RREG32(R600_GENERAL_PWRMGT);
417926deccbSFrançois Tigeot low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL);
418926deccbSFrançois Tigeot medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL);
419926deccbSFrançois Tigeot high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL);
420926deccbSFrançois Tigeot ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL);
421926deccbSFrançois Tigeot lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE);
422926deccbSFrançois Tigeot
423926deccbSFrançois Tigeot /* disable VIP */
424926deccbSFrançois Tigeot WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
425926deccbSFrançois Tigeot /* enable the rom */
426926deccbSFrançois Tigeot WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
427926deccbSFrançois Tigeot /* Disable VGA mode */
428926deccbSFrançois Tigeot WREG32(AVIVO_D1VGA_CONTROL,
429926deccbSFrançois Tigeot (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
430926deccbSFrançois Tigeot AVIVO_DVGA_CONTROL_TIMING_SELECT)));
431926deccbSFrançois Tigeot WREG32(AVIVO_D2VGA_CONTROL,
432926deccbSFrançois Tigeot (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
433926deccbSFrançois Tigeot AVIVO_DVGA_CONTROL_TIMING_SELECT)));
434926deccbSFrançois Tigeot WREG32(AVIVO_VGA_RENDER_CONTROL,
435926deccbSFrançois Tigeot (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
436926deccbSFrançois Tigeot
437926deccbSFrançois Tigeot WREG32(R600_ROM_CNTL,
438926deccbSFrançois Tigeot ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) |
439926deccbSFrançois Tigeot (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) |
440926deccbSFrançois Tigeot R600_SCK_OVERWRITE));
441926deccbSFrançois Tigeot
442926deccbSFrançois Tigeot WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS));
443926deccbSFrançois Tigeot WREG32(R600_LOW_VID_LOWER_GPIO_CNTL,
444926deccbSFrançois Tigeot (low_vid_lower_gpio_cntl & ~0x400));
445926deccbSFrançois Tigeot WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL,
446926deccbSFrançois Tigeot (medium_vid_lower_gpio_cntl & ~0x400));
447926deccbSFrançois Tigeot WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL,
448926deccbSFrançois Tigeot (high_vid_lower_gpio_cntl & ~0x400));
449926deccbSFrançois Tigeot WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL,
450926deccbSFrançois Tigeot (ctxsw_vid_lower_gpio_cntl & ~0x400));
451926deccbSFrançois Tigeot WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400));
452926deccbSFrançois Tigeot
453926deccbSFrançois Tigeot r = radeon_read_bios(rdev);
454926deccbSFrançois Tigeot
455926deccbSFrançois Tigeot /* restore regs */
456926deccbSFrançois Tigeot WREG32(RADEON_VIPH_CONTROL, viph_control);
457926deccbSFrançois Tigeot WREG32(R600_BUS_CNTL, bus_cntl);
458926deccbSFrançois Tigeot WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
459926deccbSFrançois Tigeot WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
460926deccbSFrançois Tigeot WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
461926deccbSFrançois Tigeot WREG32(R600_ROM_CNTL, rom_cntl);
462926deccbSFrançois Tigeot WREG32(R600_GENERAL_PWRMGT, general_pwrmgt);
463926deccbSFrançois Tigeot WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl);
464926deccbSFrançois Tigeot WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl);
465926deccbSFrançois Tigeot WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl);
466926deccbSFrançois Tigeot WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl);
467926deccbSFrançois Tigeot WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable);
468926deccbSFrançois Tigeot return r;
469926deccbSFrançois Tigeot }
470926deccbSFrançois Tigeot
471926deccbSFrançois Tigeot static bool avivo_read_disabled_bios(struct radeon_device *rdev)
472926deccbSFrançois Tigeot {
473926deccbSFrançois Tigeot uint32_t seprom_cntl1;
474926deccbSFrançois Tigeot uint32_t viph_control;
475926deccbSFrançois Tigeot uint32_t bus_cntl;
476926deccbSFrançois Tigeot uint32_t d1vga_control;
477926deccbSFrançois Tigeot uint32_t d2vga_control;
478926deccbSFrançois Tigeot uint32_t vga_render_control;
479926deccbSFrançois Tigeot uint32_t gpiopad_a;
480926deccbSFrançois Tigeot uint32_t gpiopad_en;
481926deccbSFrançois Tigeot uint32_t gpiopad_mask;
482926deccbSFrançois Tigeot bool r;
483926deccbSFrançois Tigeot
484926deccbSFrançois Tigeot DRM_INFO("%s: ===> Try disabled BIOS (avivo)...\n", __func__);
485926deccbSFrançois Tigeot
486926deccbSFrançois Tigeot seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
487926deccbSFrançois Tigeot viph_control = RREG32(RADEON_VIPH_CONTROL);
488926deccbSFrançois Tigeot bus_cntl = RREG32(RV370_BUS_CNTL);
489926deccbSFrançois Tigeot d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
490926deccbSFrançois Tigeot d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
491926deccbSFrançois Tigeot vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
492926deccbSFrançois Tigeot gpiopad_a = RREG32(RADEON_GPIOPAD_A);
493926deccbSFrançois Tigeot gpiopad_en = RREG32(RADEON_GPIOPAD_EN);
494926deccbSFrançois Tigeot gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK);
495926deccbSFrançois Tigeot
496926deccbSFrançois Tigeot WREG32(RADEON_SEPROM_CNTL1,
497926deccbSFrançois Tigeot ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
498926deccbSFrançois Tigeot (0xc << RADEON_SCK_PRESCALE_SHIFT)));
499926deccbSFrançois Tigeot WREG32(RADEON_GPIOPAD_A, 0);
500926deccbSFrançois Tigeot WREG32(RADEON_GPIOPAD_EN, 0);
501926deccbSFrançois Tigeot WREG32(RADEON_GPIOPAD_MASK, 0);
502926deccbSFrançois Tigeot
503926deccbSFrançois Tigeot /* disable VIP */
504926deccbSFrançois Tigeot WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
505926deccbSFrançois Tigeot
506926deccbSFrançois Tigeot /* enable the rom */
507926deccbSFrançois Tigeot WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));
508926deccbSFrançois Tigeot
509926deccbSFrançois Tigeot /* Disable VGA mode */
510926deccbSFrançois Tigeot WREG32(AVIVO_D1VGA_CONTROL,
511926deccbSFrançois Tigeot (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
512926deccbSFrançois Tigeot AVIVO_DVGA_CONTROL_TIMING_SELECT)));
513926deccbSFrançois Tigeot WREG32(AVIVO_D2VGA_CONTROL,
514926deccbSFrançois Tigeot (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
515926deccbSFrançois Tigeot AVIVO_DVGA_CONTROL_TIMING_SELECT)));
516926deccbSFrançois Tigeot WREG32(AVIVO_VGA_RENDER_CONTROL,
517926deccbSFrançois Tigeot (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
518926deccbSFrançois Tigeot
519926deccbSFrançois Tigeot r = radeon_read_bios(rdev);
520926deccbSFrançois Tigeot
521926deccbSFrançois Tigeot /* restore regs */
522926deccbSFrançois Tigeot WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
523926deccbSFrançois Tigeot WREG32(RADEON_VIPH_CONTROL, viph_control);
524926deccbSFrançois Tigeot WREG32(RV370_BUS_CNTL, bus_cntl);
525926deccbSFrançois Tigeot WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
526926deccbSFrançois Tigeot WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
527926deccbSFrançois Tigeot WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
528926deccbSFrançois Tigeot WREG32(RADEON_GPIOPAD_A, gpiopad_a);
529926deccbSFrançois Tigeot WREG32(RADEON_GPIOPAD_EN, gpiopad_en);
530926deccbSFrançois Tigeot WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask);
531926deccbSFrançois Tigeot return r;
532926deccbSFrançois Tigeot }
533926deccbSFrançois Tigeot
534926deccbSFrançois Tigeot static bool legacy_read_disabled_bios(struct radeon_device *rdev)
535926deccbSFrançois Tigeot {
536926deccbSFrançois Tigeot uint32_t seprom_cntl1;
537926deccbSFrançois Tigeot uint32_t viph_control;
538926deccbSFrançois Tigeot uint32_t bus_cntl;
539926deccbSFrançois Tigeot uint32_t crtc_gen_cntl;
540926deccbSFrançois Tigeot uint32_t crtc2_gen_cntl;
541926deccbSFrançois Tigeot uint32_t crtc_ext_cntl;
542926deccbSFrançois Tigeot uint32_t fp2_gen_cntl;
543926deccbSFrançois Tigeot bool r;
544926deccbSFrançois Tigeot
545926deccbSFrançois Tigeot DRM_INFO("%s: ===> Try disabled BIOS (legacy)...\n", __func__);
546926deccbSFrançois Tigeot
547926deccbSFrançois Tigeot seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
548926deccbSFrançois Tigeot viph_control = RREG32(RADEON_VIPH_CONTROL);
549926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_PCIE)
550926deccbSFrançois Tigeot bus_cntl = RREG32(RV370_BUS_CNTL);
551926deccbSFrançois Tigeot else
552926deccbSFrançois Tigeot bus_cntl = RREG32(RADEON_BUS_CNTL);
553926deccbSFrançois Tigeot crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
554926deccbSFrançois Tigeot crtc2_gen_cntl = 0;
555926deccbSFrançois Tigeot crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
556926deccbSFrançois Tigeot fp2_gen_cntl = 0;
557926deccbSFrançois Tigeot
558926deccbSFrançois Tigeot #define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159
559926deccbSFrançois Tigeot
560c6f73aabSFrançois Tigeot if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
561926deccbSFrançois Tigeot fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
562926deccbSFrançois Tigeot }
563926deccbSFrançois Tigeot
564926deccbSFrançois Tigeot if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
565926deccbSFrançois Tigeot crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
566926deccbSFrançois Tigeot }
567926deccbSFrançois Tigeot
568926deccbSFrançois Tigeot WREG32(RADEON_SEPROM_CNTL1,
569926deccbSFrançois Tigeot ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
570926deccbSFrançois Tigeot (0xc << RADEON_SCK_PRESCALE_SHIFT)));
571926deccbSFrançois Tigeot
572926deccbSFrançois Tigeot /* disable VIP */
573926deccbSFrançois Tigeot WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
574926deccbSFrançois Tigeot
575926deccbSFrançois Tigeot /* enable the rom */
576926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_PCIE)
577926deccbSFrançois Tigeot WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));
578926deccbSFrançois Tigeot else
579926deccbSFrançois Tigeot WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
580926deccbSFrançois Tigeot
581926deccbSFrançois Tigeot /* Turn off mem requests and CRTC for both controllers */
582926deccbSFrançois Tigeot WREG32(RADEON_CRTC_GEN_CNTL,
583926deccbSFrançois Tigeot ((crtc_gen_cntl & ~RADEON_CRTC_EN) |
584926deccbSFrançois Tigeot (RADEON_CRTC_DISP_REQ_EN_B |
585926deccbSFrançois Tigeot RADEON_CRTC_EXT_DISP_EN)));
586926deccbSFrançois Tigeot if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
587926deccbSFrançois Tigeot WREG32(RADEON_CRTC2_GEN_CNTL,
588926deccbSFrançois Tigeot ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) |
589926deccbSFrançois Tigeot RADEON_CRTC2_DISP_REQ_EN_B));
590926deccbSFrançois Tigeot }
591926deccbSFrançois Tigeot /* Turn off CRTC */
592926deccbSFrançois Tigeot WREG32(RADEON_CRTC_EXT_CNTL,
593926deccbSFrançois Tigeot ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) |
594926deccbSFrançois Tigeot (RADEON_CRTC_SYNC_TRISTAT |
595926deccbSFrançois Tigeot RADEON_CRTC_DISPLAY_DIS)));
596926deccbSFrançois Tigeot
597c6f73aabSFrançois Tigeot if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
598926deccbSFrançois Tigeot WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON));
599926deccbSFrançois Tigeot }
600926deccbSFrançois Tigeot
601926deccbSFrançois Tigeot r = radeon_read_bios(rdev);
602926deccbSFrançois Tigeot
603926deccbSFrançois Tigeot /* restore regs */
604926deccbSFrançois Tigeot WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
605926deccbSFrançois Tigeot WREG32(RADEON_VIPH_CONTROL, viph_control);
606926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_PCIE)
607926deccbSFrançois Tigeot WREG32(RV370_BUS_CNTL, bus_cntl);
608926deccbSFrançois Tigeot else
609926deccbSFrançois Tigeot WREG32(RADEON_BUS_CNTL, bus_cntl);
610926deccbSFrançois Tigeot WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
611926deccbSFrançois Tigeot if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
612926deccbSFrançois Tigeot WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
613926deccbSFrançois Tigeot }
614926deccbSFrançois Tigeot WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
615c6f73aabSFrançois Tigeot if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
616926deccbSFrançois Tigeot WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
617926deccbSFrançois Tigeot }
618926deccbSFrançois Tigeot return r;
619926deccbSFrançois Tigeot }
620926deccbSFrançois Tigeot
621926deccbSFrançois Tigeot static bool radeon_read_disabled_bios(struct radeon_device *rdev)
622926deccbSFrançois Tigeot {
623926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_IGP)
624926deccbSFrançois Tigeot return igp_read_bios_from_vram(rdev);
625926deccbSFrançois Tigeot else if (rdev->family >= CHIP_BARTS)
626926deccbSFrançois Tigeot return ni_read_disabled_bios(rdev);
627926deccbSFrançois Tigeot else if (rdev->family >= CHIP_RV770)
628926deccbSFrançois Tigeot return r700_read_disabled_bios(rdev);
629926deccbSFrançois Tigeot else if (rdev->family >= CHIP_R600)
630926deccbSFrançois Tigeot return r600_read_disabled_bios(rdev);
631926deccbSFrançois Tigeot else if (rdev->family >= CHIP_RS600)
632926deccbSFrançois Tigeot return avivo_read_disabled_bios(rdev);
633926deccbSFrançois Tigeot else
634926deccbSFrançois Tigeot return legacy_read_disabled_bios(rdev);
635926deccbSFrançois Tigeot }
636926deccbSFrançois Tigeot
637452a88ebSzrj #ifdef CONFIG_ACPI
638926deccbSFrançois Tigeot static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
639926deccbSFrançois Tigeot {
640*a85cb24fSFrançois Tigeot bool ret = false;
641926deccbSFrançois Tigeot ACPI_TABLE_HEADER *hdr;
642926deccbSFrançois Tigeot ACPI_SIZE tbl_size;
643926deccbSFrançois Tigeot UEFI_ACPI_VFCT *vfct;
644*a85cb24fSFrançois Tigeot GOP_VBIOS_CONTENT *vbios;
645*a85cb24fSFrançois Tigeot VFCT_IMAGE_HEADER *vhdr;
646*a85cb24fSFrançois Tigeot ACPI_STATUS status;
647926deccbSFrançois Tigeot
648*a85cb24fSFrançois Tigeot DRM_INFO("%s: ===> Try VFCT...\n", __func__);
649*a85cb24fSFrançois Tigeot
650*a85cb24fSFrançois Tigeot DRM_INFO("%s: Get \"VFCT\" ACPI table\n", __func__);
651*a85cb24fSFrançois Tigeot status = AcpiGetTable("VFCT", 1, &hdr);
652*a85cb24fSFrançois Tigeot if (!ACPI_SUCCESS(status)) {
653*a85cb24fSFrançois Tigeot DRM_INFO("%s: Failed to get \"VFCT\" table: %s\n",
654*a85cb24fSFrançois Tigeot __func__, AcpiFormatException(status));
655926deccbSFrançois Tigeot return false;
656*a85cb24fSFrançois Tigeot }
657926deccbSFrançois Tigeot tbl_size = hdr->Length;
658926deccbSFrançois Tigeot if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
659926deccbSFrançois Tigeot DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
660*a85cb24fSFrançois Tigeot goto out_unmap;
661926deccbSFrançois Tigeot }
662926deccbSFrançois Tigeot
663926deccbSFrançois Tigeot vfct = (UEFI_ACPI_VFCT *)hdr;
664*a85cb24fSFrançois Tigeot if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
6654be47400SFrançois Tigeot DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
666*a85cb24fSFrançois Tigeot goto out_unmap;
667*a85cb24fSFrançois Tigeot }
668*a85cb24fSFrançois Tigeot
669*a85cb24fSFrançois Tigeot vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
670*a85cb24fSFrançois Tigeot vhdr = &vbios->VbiosHeader;
671*a85cb24fSFrançois Tigeot DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n",
672*a85cb24fSFrançois Tigeot vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction,
673*a85cb24fSFrançois Tigeot vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength);
674*a85cb24fSFrançois Tigeot
675*a85cb24fSFrançois Tigeot if (vhdr->PCIBus != rdev->pdev->bus->number ||
676*a85cb24fSFrançois Tigeot vhdr->PCIDevice != rdev->ddev->pci_slot ||
677*a85cb24fSFrançois Tigeot vhdr->PCIFunction != rdev->ddev->pci_func ||
678*a85cb24fSFrançois Tigeot vhdr->VendorID != rdev->pdev->vendor ||
679*a85cb24fSFrançois Tigeot vhdr->DeviceID != rdev->pdev->device) {
680*a85cb24fSFrançois Tigeot DRM_INFO("ACPI VFCT table is not for this card\n");
681*a85cb24fSFrançois Tigeot goto out_unmap;
682*a85cb24fSFrançois Tigeot }
683*a85cb24fSFrançois Tigeot
684*a85cb24fSFrançois Tigeot if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
685*a85cb24fSFrançois Tigeot DRM_ERROR("ACPI VFCT image truncated\n");
686*a85cb24fSFrançois Tigeot goto out_unmap;
687*a85cb24fSFrançois Tigeot }
688*a85cb24fSFrançois Tigeot
689*a85cb24fSFrançois Tigeot rdev->bios = kmalloc(vhdr->ImageLength, M_DRM, M_WAITOK);
690*a85cb24fSFrançois Tigeot memcpy(rdev->bios, &vbios->VbiosContent, vhdr->ImageLength);
691*a85cb24fSFrançois Tigeot ret = !!rdev->bios;
692*a85cb24fSFrançois Tigeot
693*a85cb24fSFrançois Tigeot out_unmap:
694*a85cb24fSFrançois Tigeot return ret;
695926deccbSFrançois Tigeot }
696452a88ebSzrj #else
697452a88ebSzrj static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
698452a88ebSzrj {
699452a88ebSzrj return false;
700452a88ebSzrj }
701452a88ebSzrj #endif
702926deccbSFrançois Tigeot
703926deccbSFrançois Tigeot bool radeon_get_bios(struct radeon_device *rdev)
704926deccbSFrançois Tigeot {
705926deccbSFrançois Tigeot bool r;
706926deccbSFrançois Tigeot uint16_t tmp;
707926deccbSFrançois Tigeot
708926deccbSFrançois Tigeot r = radeon_atrm_get_bios(rdev);
709926deccbSFrançois Tigeot if (r == false)
710926deccbSFrançois Tigeot r = radeon_acpi_vfct_bios(rdev);
711926deccbSFrançois Tigeot if (r == false)
712926deccbSFrançois Tigeot r = igp_read_bios_from_vram(rdev);
713926deccbSFrançois Tigeot if (r == false)
714926deccbSFrançois Tigeot r = radeon_read_bios(rdev);
715591d5043SFrançois Tigeot if (r == false)
716926deccbSFrançois Tigeot r = radeon_read_disabled_bios(rdev);
717591d5043SFrançois Tigeot if (r == false)
718b403bed8SMichael Neumann r = radeon_read_platform_bios(rdev);
719926deccbSFrançois Tigeot if (r == false || rdev->bios == NULL) {
720926deccbSFrançois Tigeot DRM_ERROR("Unable to locate a BIOS ROM\n");
721926deccbSFrançois Tigeot rdev->bios = NULL;
722926deccbSFrançois Tigeot return false;
723926deccbSFrançois Tigeot }
724926deccbSFrançois Tigeot if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
725c4ef309bSzrj printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]);
726926deccbSFrançois Tigeot goto free_bios;
727926deccbSFrançois Tigeot }
728926deccbSFrançois Tigeot
729926deccbSFrançois Tigeot tmp = RBIOS16(0x18);
730926deccbSFrançois Tigeot if (RBIOS8(tmp + 0x14) != 0x0) {
731926deccbSFrançois Tigeot DRM_INFO("Not an x86 BIOS ROM, not using.\n");
732926deccbSFrançois Tigeot goto free_bios;
733926deccbSFrançois Tigeot }
734926deccbSFrançois Tigeot
735926deccbSFrançois Tigeot rdev->bios_header_start = RBIOS16(0x48);
736926deccbSFrançois Tigeot if (!rdev->bios_header_start) {
737926deccbSFrançois Tigeot goto free_bios;
738926deccbSFrançois Tigeot }
739926deccbSFrançois Tigeot tmp = rdev->bios_header_start + 4;
740926deccbSFrançois Tigeot if (!memcmp(rdev->bios + tmp, "ATOM", 4) ||
741926deccbSFrançois Tigeot !memcmp(rdev->bios + tmp, "MOTA", 4)) {
742926deccbSFrançois Tigeot rdev->is_atom_bios = true;
743926deccbSFrançois Tigeot } else {
744926deccbSFrançois Tigeot rdev->is_atom_bios = false;
745926deccbSFrançois Tigeot }
746926deccbSFrançois Tigeot
747926deccbSFrançois Tigeot DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM");
748926deccbSFrançois Tigeot return true;
749926deccbSFrançois Tigeot free_bios:
750c4ef309bSzrj kfree(rdev->bios);
751926deccbSFrançois Tigeot rdev->bios = NULL;
752926deccbSFrançois Tigeot return false;
753926deccbSFrançois Tigeot }
754