Rev 2005 | Rev 3764 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2005 | Rev 2997 | ||
---|---|---|---|
Line 23... | Line 23... | ||
23 | * |
23 | * |
24 | * Authors: Dave Airlie |
24 | * Authors: Dave Airlie |
25 | * Alex Deucher |
25 | * Alex Deucher |
26 | * Jerome Glisse |
26 | * Jerome Glisse |
27 | */ |
27 | */ |
28 | #include "drmP.h" |
28 | #include |
29 | #include "radeon_reg.h" |
29 | #include "radeon_reg.h" |
30 | #include "radeon.h" |
30 | #include "radeon.h" |
31 | #include "atom.h" |
31 | #include "atom.h" |
Line 32... | Line 32... | ||
32 | 32 | ||
Line 97... | Line 97... | ||
97 | memcpy(rdev->bios, bios, size); |
97 | memcpy(rdev->bios, bios, size); |
98 | // pci_unmap_rom(rdev->pdev, bios); |
98 | // pci_unmap_rom(rdev->pdev, bios); |
99 | return true; |
99 | return true; |
100 | } |
100 | } |
Line -... | Line 101... | ||
- | 101 | ||
101 | 102 | #ifdef CONFIG_ACPI |
|
102 | /* 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 |
103 | * dual-gpu systems. |
104 | * dual-gpu systems. |
- | 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 | */ |
|
- | 120 | static 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 | } |
|
104 | */ |
149 | |
105 | static bool radeon_atrm_get_bios(struct radeon_device *rdev) |
150 | static bool radeon_atrm_get_bios(struct radeon_device *rdev) |
106 | { |
151 | { |
107 | int ret; |
152 | int ret; |
108 | int size = 256 * 1024; |
153 | int size = 256 * 1024; |
- | 154 | int i; |
|
- | 155 | struct pci_dev *pdev = NULL; |
|
- | 156 | acpi_handle dhandle, atrm_handle; |
|
- | 157 | acpi_status status; |
|
Line -... | Line 158... | ||
- | 158 | bool found = false; |
|
- | 159 | ||
- | 160 | /* ATRM is for the discrete card only */ |
|
- | 161 | if (rdev->flags & RADEON_IS_IGP) |
|
- | 162 | return false; |
|
109 | int i; |
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 | } |
|
110 | 175 | ||
Line 111... | Line 176... | ||
111 | if (!radeon_atrm_supported(rdev->pdev)) |
176 | if (!found) |
112 | return false; |
177 | return false; |
113 | 178 | ||
114 | rdev->bios = kmalloc(size, GFP_KERNEL); |
179 | rdev->bios = kmalloc(size, GFP_KERNEL); |
115 | if (!rdev->bios) { |
180 | if (!rdev->bios) { |
Line 116... | Line 181... | ||
116 | DRM_ERROR("Unable to allocate bios\n"); |
181 | DRM_ERROR("Unable to allocate bios\n"); |
117 | return false; |
182 | return false; |
- | 183 | } |
|
118 | } |
184 | |
119 | 185 | for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { |
|
120 | for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { |
186 | ret = radeon_atrm_call(atrm_handle, |
121 | ret = radeon_atrm_get_bios_chunk(rdev->bios, |
187 | rdev->bios, |
122 | (i * ATRM_BIOS_PAGE), |
188 | (i * ATRM_BIOS_PAGE), |
Line 123... | Line 189... | ||
123 | ATRM_BIOS_PAGE); |
189 | ATRM_BIOS_PAGE); |
124 | if (ret <= 0) |
190 | if (ret < ATRM_BIOS_PAGE) |
125 | break; |
191 | break; |
126 | } |
192 | } |
127 | 193 | ||
128 | if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { |
194 | if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { |
- | 195 | kfree(rdev->bios); |
|
- | 196 | return false; |
|
- | 197 | } |
|
- | 198 | return true; |
|
- | 199 | } |
|
- | 200 | #else |
|
Line 129... | Line 201... | ||
129 | kfree(rdev->bios); |
201 | static bool radeon_atrm_get_bios(struct radeon_device *rdev) |
130 | return false; |
202 | { |
131 | } |
203 | return false; |
132 | return true; |
204 | } |
Line 475... | Line 547... | ||
475 | return avivo_read_disabled_bios(rdev); |
547 | return avivo_read_disabled_bios(rdev); |
476 | else |
548 | else |
477 | return legacy_read_disabled_bios(rdev); |
549 | return legacy_read_disabled_bios(rdev); |
478 | } |
550 | } |
Line -... | Line 551... | ||
- | 551 | ||
- | 552 | #ifdef CONFIG_ACPI |
|
- | 553 | static 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 | ||
- | 598 | out_unmap: |
|
- | 599 | return ret; |
|
- | 600 | } |
|
- | 601 | #else |
|
- | 602 | static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) |
|
- | 603 | { |
|
- | 604 | return false; |
|
- | 605 | } |
|
Line 479... | Line 606... | ||
479 | 606 | #endif |
|
480 | 607 | ||
481 | bool radeon_get_bios(struct radeon_device *rdev) |
608 | bool radeon_get_bios(struct radeon_device *rdev) |
482 | { |
609 | { |
Line 483... | Line 610... | ||
483 | bool r; |
610 | bool r; |
484 | uint16_t tmp; |
611 | uint16_t tmp; |
- | 612 | ||
- | 613 | r = radeon_atrm_get_bios(rdev); |
|
485 | 614 | if (r == false) |
|
486 | r = radeon_atrm_get_bios(rdev); |
615 | r = radeon_acpi_vfct_bios(rdev); |
487 | if (r == false) |
616 | if (r == false) |
488 | r = igp_read_bios_from_vram(rdev); |
617 | r = igp_read_bios_from_vram(rdev); |
489 | if (r == false) |
618 | if (r == false) |