Commit 052c2990 authored by Alex Deucher's avatar Alex Deucher

drm/amdgpu: add atpx quirk handling (v2)

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: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: Junwei Zhang <Jerry.Zhang@amd.com> (v2)
Reviewed-and-Tested-by: default avatarJunwei Zhang <Jerry.Zhang@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Cc: stable@vger.kernel.org
parent f2e5262f
...@@ -14,6 +14,16 @@ ...@@ -14,6 +14,16 @@
#include "amd_acpi.h" #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 { struct amdgpu_atpx_functions {
bool px_params; bool px_params;
bool power_cntl; bool power_cntl;
...@@ -35,6 +45,7 @@ struct amdgpu_atpx { ...@@ -35,6 +45,7 @@ struct amdgpu_atpx {
static struct amdgpu_atpx_priv { static struct amdgpu_atpx_priv {
bool atpx_detected; bool atpx_detected;
bool bridge_pm_usable; bool bridge_pm_usable;
unsigned int quirks;
/* handle for device - and atpx */ /* handle for device - and atpx */
acpi_handle dhandle; acpi_handle dhandle;
acpi_handle other_handle; acpi_handle other_handle;
...@@ -205,13 +216,19 @@ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx) ...@@ -205,13 +216,19 @@ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
atpx->is_hybrid = false; atpx->is_hybrid = false;
if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) { if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
printk("ATPX Hybrid Graphics\n"); if (amdgpu_atpx_priv.quirks & AMDGPU_PX_QUIRK_FORCE_ATPX) {
/* printk("ATPX Hybrid Graphics, forcing to ATPX\n");
* Disable legacy PM methods only when pcie port PM is usable, atpx->functions.power_cntl = true;
* otherwise the device might fail to power off or power on. atpx->is_hybrid = false;
*/ } else {
atpx->functions.power_cntl = !amdgpu_atpx_priv.bridge_pm_usable; printk("ATPX Hybrid Graphics\n");
atpx->is_hybrid = true; /*
* 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; atpx->dgpu_req_power_for_displays = false;
...@@ -547,6 +564,30 @@ static const struct vga_switcheroo_handler amdgpu_atpx_handler = { ...@@ -547,6 +564,30 @@ static const struct vga_switcheroo_handler amdgpu_atpx_handler = {
.get_client_id = amdgpu_atpx_get_client_id, .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 * amdgpu_atpx_detect - detect whether we have PX
* *
...@@ -570,6 +611,7 @@ static bool amdgpu_atpx_detect(void) ...@@ -570,6 +611,7 @@ static bool amdgpu_atpx_detect(void)
parent_pdev = pci_upstream_bridge(pdev); parent_pdev = pci_upstream_bridge(pdev);
d3_supported |= parent_pdev && parent_pdev->bridge_d3; 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) { while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
...@@ -579,6 +621,7 @@ static bool amdgpu_atpx_detect(void) ...@@ -579,6 +621,7 @@ static bool amdgpu_atpx_detect(void)
parent_pdev = pci_upstream_bridge(pdev); parent_pdev = pci_upstream_bridge(pdev);
d3_supported |= parent_pdev && parent_pdev->bridge_d3; d3_supported |= parent_pdev && parent_pdev->bridge_d3;
amdgpu_atpx_get_quirks(pdev);
} }
if (has_atpx && vga_count == 2) { if (has_atpx && vga_count == 2) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment