diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index c13c51af0b68..e2c3c5ec42d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | |||
@@ -14,6 +14,16 @@ | |||
14 | 14 | ||
15 | #include "amd_acpi.h" | 15 | #include "amd_acpi.h" |
16 | 16 | ||
17 | #define AMDGPU_PX_QUIRK_FORCE_ATPX (1 << 0) | ||
18 | |||
19 | struct amdgpu_px_quirk { | ||
20 | u32 chip_vendor; | ||
21 | u32 chip_device; | ||
22 | u32 subsys_vendor; | ||
23 | u32 subsys_device; | ||
24 | u32 px_quirk_flags; | ||
25 | }; | ||
26 | |||
17 | struct amdgpu_atpx_functions { | 27 | struct amdgpu_atpx_functions { |
18 | bool px_params; | 28 | bool px_params; |
19 | bool power_cntl; | 29 | bool power_cntl; |
@@ -35,6 +45,7 @@ struct amdgpu_atpx { | |||
35 | static struct amdgpu_atpx_priv { | 45 | static struct amdgpu_atpx_priv { |
36 | bool atpx_detected; | 46 | bool atpx_detected; |
37 | bool bridge_pm_usable; | 47 | bool bridge_pm_usable; |
48 | unsigned int quirks; | ||
38 | /* handle for device - and atpx */ | 49 | /* handle for device - and atpx */ |
39 | acpi_handle dhandle; | 50 | acpi_handle dhandle; |
40 | acpi_handle other_handle; | 51 | acpi_handle other_handle; |
@@ -205,13 +216,19 @@ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx) | |||
205 | 216 | ||
206 | atpx->is_hybrid = false; | 217 | atpx->is_hybrid = false; |
207 | if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) { | 218 | if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) { |
208 | printk("ATPX Hybrid Graphics\n"); | 219 | if (amdgpu_atpx_priv.quirks & AMDGPU_PX_QUIRK_FORCE_ATPX) { |
209 | /* | 220 | printk("ATPX Hybrid Graphics, forcing to ATPX\n"); |
210 | * Disable legacy PM methods only when pcie port PM is usable, | 221 | atpx->functions.power_cntl = true; |
211 | * otherwise the device might fail to power off or power on. | 222 | atpx->is_hybrid = false; |
212 | */ | 223 | } else { |
213 | atpx->functions.power_cntl = !amdgpu_atpx_priv.bridge_pm_usable; | 224 | printk("ATPX Hybrid Graphics\n"); |
214 | atpx->is_hybrid = true; | 225 | /* |
226 | * Disable legacy PM methods only when pcie port PM is usable, | ||
227 | * otherwise the device might fail to power off or power on. | ||
228 | */ | ||
229 | atpx->functions.power_cntl = !amdgpu_atpx_priv.bridge_pm_usable; | ||
230 | atpx->is_hybrid = true; | ||
231 | } | ||
215 | } | 232 | } |
216 | 233 | ||
217 | atpx->dgpu_req_power_for_displays = false; | 234 | atpx->dgpu_req_power_for_displays = false; |
@@ -547,6 +564,30 @@ static const struct vga_switcheroo_handler amdgpu_atpx_handler = { | |||
547 | .get_client_id = amdgpu_atpx_get_client_id, | 564 | .get_client_id = amdgpu_atpx_get_client_id, |
548 | }; | 565 | }; |
549 | 566 | ||
567 | static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = { | ||
568 | /* HG _PR3 doesn't seem to work on this A+A weston board */ | ||
569 | { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX }, | ||
570 | { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX }, | ||
571 | { 0, 0, 0, 0, 0 }, | ||
572 | }; | ||
573 | |||
574 | static void amdgpu_atpx_get_quirks(struct pci_dev *pdev) | ||
575 | { | ||
576 | const struct amdgpu_px_quirk *p = amdgpu_px_quirk_list; | ||
577 | |||
578 | /* Apply PX quirks */ | ||
579 | while (p && p->chip_device != 0) { | ||
580 | if (pdev->vendor == p->chip_vendor && | ||
581 | pdev->device == p->chip_device && | ||
582 | pdev->subsystem_vendor == p->subsys_vendor && | ||
583 | pdev->subsystem_device == p->subsys_device) { | ||
584 | amdgpu_atpx_priv.quirks |= p->px_quirk_flags; | ||
585 | break; | ||
586 | } | ||
587 | ++p; | ||
588 | } | ||
589 | } | ||
590 | |||
550 | /** | 591 | /** |
551 | * amdgpu_atpx_detect - detect whether we have PX | 592 | * amdgpu_atpx_detect - detect whether we have PX |
552 | * | 593 | * |
@@ -570,6 +611,7 @@ static bool amdgpu_atpx_detect(void) | |||
570 | 611 | ||
571 | parent_pdev = pci_upstream_bridge(pdev); | 612 | parent_pdev = pci_upstream_bridge(pdev); |
572 | d3_supported |= parent_pdev && parent_pdev->bridge_d3; | 613 | d3_supported |= parent_pdev && parent_pdev->bridge_d3; |
614 | amdgpu_atpx_get_quirks(pdev); | ||
573 | } | 615 | } |
574 | 616 | ||
575 | while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { | 617 | while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { |
@@ -579,6 +621,7 @@ static bool amdgpu_atpx_detect(void) | |||
579 | 621 | ||
580 | parent_pdev = pci_upstream_bridge(pdev); | 622 | parent_pdev = pci_upstream_bridge(pdev); |
581 | d3_supported |= parent_pdev && parent_pdev->bridge_d3; | 623 | d3_supported |= parent_pdev && parent_pdev->bridge_d3; |
624 | amdgpu_atpx_get_quirks(pdev); | ||
582 | } | 625 | } |
583 | 626 | ||
584 | if (has_atpx && vga_count == 2) { | 627 | if (has_atpx && vga_count == 2) { |