| From 052c299080cd6859f82a8154a7a673fafabe644c Mon Sep 17 00:00:00 2001 |
| From: Alex Deucher <alexander.deucher@amd.com> |
| Date: Wed, 20 Dec 2017 13:29:58 -0500 |
| Subject: drm/amdgpu: add atpx quirk handling (v2) |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Alex Deucher <alexander.deucher@amd.com> |
| |
| commit 052c299080cd6859f82a8154a7a673fafabe644c upstream. |
| |
| Add quirks for handling PX/HG systems. In this case, add |
| a quirk for a weston dGPU that only seems to properly power |
| down using ATPX power control rather than HG (_PR3). |
| |
| v2: append a new weston XT |
| |
| Signed-off-by: Alex Deucher <alexander.deucher@amd.com> |
| Signed-off-by: Junwei Zhang <Jerry.Zhang@amd.com> (v2) |
| Reviewed-and-Tested-by: Junwei Zhang <Jerry.Zhang@amd.com> |
| Reviewed-by: Alex Deucher <alexander.deucher@amd.com> |
| Acked-by: Christian Kรถnig <christian.koenig@amd.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 57 ++++++++++++++++++++--- |
| 1 file changed, 50 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c |
| +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c |
| @@ -14,6 +14,16 @@ |
| |
| #include "amd_acpi.h" |
| |
| +#define AMDGPU_PX_QUIRK_FORCE_ATPX (1 << 0) |
| + |
| +struct amdgpu_px_quirk { |
| + u32 chip_vendor; |
| + u32 chip_device; |
| + u32 subsys_vendor; |
| + u32 subsys_device; |
| + u32 px_quirk_flags; |
| +}; |
| + |
| struct amdgpu_atpx_functions { |
| bool px_params; |
| bool power_cntl; |
| @@ -35,6 +45,7 @@ struct amdgpu_atpx { |
| static struct amdgpu_atpx_priv { |
| bool atpx_detected; |
| bool bridge_pm_usable; |
| + unsigned int quirks; |
| /* handle for device - and atpx */ |
| acpi_handle dhandle; |
| acpi_handle other_handle; |
| @@ -205,13 +216,19 @@ static int amdgpu_atpx_validate(struct a |
| |
| atpx->is_hybrid = false; |
| if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) { |
| - printk("ATPX Hybrid Graphics\n"); |
| - /* |
| - * Disable legacy PM methods only when pcie port PM is usable, |
| - * otherwise the device might fail to power off or power on. |
| - */ |
| - atpx->functions.power_cntl = !amdgpu_atpx_priv.bridge_pm_usable; |
| - atpx->is_hybrid = true; |
| + if (amdgpu_atpx_priv.quirks & AMDGPU_PX_QUIRK_FORCE_ATPX) { |
| + printk("ATPX Hybrid Graphics, forcing to ATPX\n"); |
| + atpx->functions.power_cntl = true; |
| + atpx->is_hybrid = false; |
| + } else { |
| + printk("ATPX Hybrid Graphics\n"); |
| + /* |
| + * Disable legacy PM methods only when pcie port PM is usable, |
| + * otherwise the device might fail to power off or power on. |
| + */ |
| + atpx->functions.power_cntl = !amdgpu_atpx_priv.bridge_pm_usable; |
| + atpx->is_hybrid = true; |
| + } |
| } |
| |
| atpx->dgpu_req_power_for_displays = false; |
| @@ -547,6 +564,30 @@ static const struct vga_switcheroo_handl |
| .get_client_id = amdgpu_atpx_get_client_id, |
| }; |
| |
| +static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = { |
| + /* HG _PR3 doesn't seem to work on this A+A weston board */ |
| + { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX }, |
| + { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX }, |
| + { 0, 0, 0, 0, 0 }, |
| +}; |
| + |
| +static void amdgpu_atpx_get_quirks(struct pci_dev *pdev) |
| +{ |
| + const struct amdgpu_px_quirk *p = amdgpu_px_quirk_list; |
| + |
| + /* Apply PX quirks */ |
| + while (p && p->chip_device != 0) { |
| + if (pdev->vendor == p->chip_vendor && |
| + pdev->device == p->chip_device && |
| + pdev->subsystem_vendor == p->subsys_vendor && |
| + pdev->subsystem_device == p->subsys_device) { |
| + amdgpu_atpx_priv.quirks |= p->px_quirk_flags; |
| + break; |
| + } |
| + ++p; |
| + } |
| +} |
| + |
| /** |
| * amdgpu_atpx_detect - detect whether we have PX |
| * |
| @@ -570,6 +611,7 @@ static bool amdgpu_atpx_detect(void) |
| |
| parent_pdev = pci_upstream_bridge(pdev); |
| d3_supported |= parent_pdev && parent_pdev->bridge_d3; |
| + amdgpu_atpx_get_quirks(pdev); |
| } |
| |
| while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { |
| @@ -579,6 +621,7 @@ static bool amdgpu_atpx_detect(void) |
| |
| parent_pdev = pci_upstream_bridge(pdev); |
| d3_supported |= parent_pdev && parent_pdev->bridge_d3; |
| + amdgpu_atpx_get_quirks(pdev); |
| } |
| |
| if (has_atpx && vga_count == 2) { |