aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_bios.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_bios.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_bios.c138
1 files changed, 134 insertions, 4 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index 501f4881e5aa..d306cc8fdeaa 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -32,6 +32,7 @@
32 32
33#include <linux/vga_switcheroo.h> 33#include <linux/vga_switcheroo.h>
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/acpi.h>
35/* 36/*
36 * BIOS. 37 * BIOS.
37 */ 38 */
@@ -98,16 +99,81 @@ static bool radeon_read_bios(struct radeon_device *rdev)
98 return true; 99 return true;
99} 100}
100 101
102#ifdef CONFIG_ACPI
101/* ATRM is used to get the BIOS on the discrete cards in 103/* ATRM is used to get the BIOS on the discrete cards in
102 * dual-gpu systems. 104 * dual-gpu systems.
103 */ 105 */
106/* retrieve the ROM in 4k blocks */
107#define ATRM_BIOS_PAGE 4096
108/**
109 * radeon_atrm_call - fetch a chunk of the vbios
110 *
111 * @atrm_handle: acpi ATRM handle
112 * @bios: vbios image pointer
113 * @offset: offset of vbios image data to fetch
114 * @len: length of vbios image data to fetch
115 *
116 * Executes ATRM to fetch a chunk of the discrete
117 * vbios image on PX systems (all asics).
118 * Returns the length of the buffer fetched.
119 */
120static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
121 int offset, int len)
122{
123 acpi_status status;
124 union acpi_object atrm_arg_elements[2], *obj;
125 struct acpi_object_list atrm_arg;
126 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
127
128 atrm_arg.count = 2;
129 atrm_arg.pointer = &atrm_arg_elements[0];
130
131 atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
132 atrm_arg_elements[0].integer.value = offset;
133
134 atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
135 atrm_arg_elements[1].integer.value = len;
136
137 status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
138 if (ACPI_FAILURE(status)) {
139 printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
140 return -ENODEV;
141 }
142
143 obj = (union acpi_object *)buffer.pointer;
144 memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
145 len = obj->buffer.length;
146 kfree(buffer.pointer);
147 return len;
148}
149
104static bool radeon_atrm_get_bios(struct radeon_device *rdev) 150static bool radeon_atrm_get_bios(struct radeon_device *rdev)
105{ 151{
106 int ret; 152 int ret;
107 int size = 256 * 1024; 153 int size = 256 * 1024;
108 int i; 154 int i;
155 struct pci_dev *pdev = NULL;
156 acpi_handle dhandle, atrm_handle;
157 acpi_status status;
158 bool found = false;
159
160 /* ATRM is for the discrete card only */
161 if (rdev->flags & RADEON_IS_IGP)
162 return false;
163
164 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
165 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
166 if (!dhandle)
167 continue;
168
169 status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
170 if (!ACPI_FAILURE(status)) {
171 found = true;
172 break;
173 }
174 }
109 175
110 if (!radeon_atrm_supported(rdev->pdev)) 176 if (!found)
111 return false; 177 return false;
112 178
113 rdev->bios = kmalloc(size, GFP_KERNEL); 179 rdev->bios = kmalloc(size, GFP_KERNEL);
@@ -117,9 +183,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
117 } 183 }
118 184
119 for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { 185 for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
120 ret = radeon_atrm_get_bios_chunk(rdev->bios, 186 ret = radeon_atrm_call(atrm_handle,
121 (i * ATRM_BIOS_PAGE), 187 rdev->bios,
122 ATRM_BIOS_PAGE); 188 (i * ATRM_BIOS_PAGE),
189 ATRM_BIOS_PAGE);
123 if (ret < ATRM_BIOS_PAGE) 190 if (ret < ATRM_BIOS_PAGE)
124 break; 191 break;
125 } 192 }
@@ -130,6 +197,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
130 } 197 }
131 return true; 198 return true;
132} 199}
200#else
201static inline bool radeon_atrm_get_bios(struct radeon_device *rdev)
202{
203 return false;
204}
205#endif
133 206
134static bool ni_read_disabled_bios(struct radeon_device *rdev) 207static bool ni_read_disabled_bios(struct radeon_device *rdev)
135{ 208{
@@ -476,6 +549,61 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev)
476 return legacy_read_disabled_bios(rdev); 549 return legacy_read_disabled_bios(rdev);
477} 550}
478 551
552#ifdef CONFIG_ACPI
553static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
554{
555 bool ret = false;
556 struct acpi_table_header *hdr;
557 acpi_size tbl_size;
558 UEFI_ACPI_VFCT *vfct;
559 GOP_VBIOS_CONTENT *vbios;
560 VFCT_IMAGE_HEADER *vhdr;
561
562 if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
563 return false;
564 if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
565 DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
566 goto out_unmap;
567 }
568
569 vfct = (UEFI_ACPI_VFCT *)hdr;
570 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
571 DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
572 goto out_unmap;
573 }
574
575 vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
576 vhdr = &vbios->VbiosHeader;
577 DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n",
578 vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction,
579 vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength);
580
581 if (vhdr->PCIBus != rdev->pdev->bus->number ||
582 vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) ||
583 vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) ||
584 vhdr->VendorID != rdev->pdev->vendor ||
585 vhdr->DeviceID != rdev->pdev->device) {
586 DRM_INFO("ACPI VFCT table is not for this card\n");
587 goto out_unmap;
588 };
589
590 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
591 DRM_ERROR("ACPI VFCT image truncated\n");
592 goto out_unmap;
593 }
594
595 rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
596 ret = !!rdev->bios;
597
598out_unmap:
599 return ret;
600}
601#else
602static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
603{
604 return false;
605}
606#endif
479 607
480bool radeon_get_bios(struct radeon_device *rdev) 608bool radeon_get_bios(struct radeon_device *rdev)
481{ 609{
@@ -484,6 +612,8 @@ bool radeon_get_bios(struct radeon_device *rdev)
484 612
485 r = radeon_atrm_get_bios(rdev); 613 r = radeon_atrm_get_bios(rdev);
486 if (r == false) 614 if (r == false)
615 r = radeon_acpi_vfct_bios(rdev);
616 if (r == false)
487 r = igp_read_bios_from_vram(rdev); 617 r = igp_read_bios_from_vram(rdev);
488 if (r == false) 618 if (r == false)
489 r = radeon_read_bios(rdev); 619 r = radeon_read_bios(rdev);