Commit 4807c5a8 authored by Alex Deucher's avatar Alex Deucher

drm/radeon: add a PX quirk list

Some PX laptops seems to have problems turning the dGPU on/off.
Add a quirk list to disable runpm by default on those systems.
Also convert the current PX d3 delay handling to a quirk.

bug:
https://bugzilla.kernel.org/show_bug.cgi?id=51381
https://bugzilla.kernel.org/show_bug.cgi?id=74551Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 391bfec3
...@@ -2353,6 +2353,7 @@ struct radeon_device { ...@@ -2353,6 +2353,7 @@ struct radeon_device {
struct dev_pm_domain vga_pm_domain; struct dev_pm_domain vga_pm_domain;
bool have_disp_power_ref; bool have_disp_power_ref;
u32 px_quirk_flags;
/* tracking pinned memory */ /* tracking pinned memory */
u64 vram_pin_size; u64 vram_pin_size;
......
...@@ -103,6 +103,31 @@ static const char radeon_family_name[][16] = { ...@@ -103,6 +103,31 @@ static const char radeon_family_name[][16] = {
"LAST", "LAST",
}; };
#define RADEON_PX_QUIRK_DISABLE_PX (1 << 0)
#define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1)
struct radeon_px_quirk {
u32 chip_vendor;
u32 chip_device;
u32 subsys_vendor;
u32 subsys_device;
u32 px_quirk_flags;
};
static struct radeon_px_quirk radeon_px_quirk_list[] = {
/* Acer aspire 5560g (CPU: AMD A4-3305M; GPU: AMD Radeon HD 6480g + 7470m)
* https://bugzilla.kernel.org/show_bug.cgi?id=74551
*/
{ PCI_VENDOR_ID_ATI, 0x6760, 0x1025, 0x0672, RADEON_PX_QUIRK_DISABLE_PX },
/* Asus K73TA laptop with AMD A6-3400M APU and Radeon 6550 GPU
* https://bugzilla.kernel.org/show_bug.cgi?id=51381
*/
{ PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x108c, RADEON_PX_QUIRK_DISABLE_PX },
/* macbook pro 8.2 */
{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
{ 0, 0, 0, 0, 0 },
};
bool radeon_is_px(struct drm_device *dev) bool radeon_is_px(struct drm_device *dev)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -112,6 +137,26 @@ bool radeon_is_px(struct drm_device *dev) ...@@ -112,6 +137,26 @@ bool radeon_is_px(struct drm_device *dev)
return false; return false;
} }
static void radeon_device_handle_px_quirks(struct radeon_device *rdev)
{
struct radeon_px_quirk *p = radeon_px_quirk_list;
/* Apply PX quirks */
while (p && p->chip_device != 0) {
if (rdev->pdev->vendor == p->chip_vendor &&
rdev->pdev->device == p->chip_device &&
rdev->pdev->subsystem_vendor == p->subsys_vendor &&
rdev->pdev->subsystem_device == p->subsys_device) {
rdev->px_quirk_flags = p->px_quirk_flags;
break;
}
++p;
}
if (rdev->px_quirk_flags & RADEON_PX_QUIRK_DISABLE_PX)
rdev->flags &= ~RADEON_IS_PX;
}
/** /**
* radeon_program_register_sequence - program an array of registers. * radeon_program_register_sequence - program an array of registers.
* *
...@@ -1092,25 +1137,6 @@ static void radeon_check_arguments(struct radeon_device *rdev) ...@@ -1092,25 +1137,6 @@ static void radeon_check_arguments(struct radeon_device *rdev)
} }
} }
/**
* radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is
* needed for waking up.
*
* @pdev: pci dev pointer
*/
static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
{
/* 6600m in a macbook pro */
if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
pdev->subsystem_device == 0x00e2) {
printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n");
return true;
}
return false;
}
/** /**
* radeon_switcheroo_set_state - set switcheroo state * radeon_switcheroo_set_state - set switcheroo state
* *
...@@ -1123,6 +1149,7 @@ static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev) ...@@ -1123,6 +1149,7 @@ static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
{ {
struct drm_device *dev = pci_get_drvdata(pdev); struct drm_device *dev = pci_get_drvdata(pdev);
struct radeon_device *rdev = dev->dev_private;
if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF)
return; return;
...@@ -1134,7 +1161,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero ...@@ -1134,7 +1161,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
/* don't suspend or resume card normally */ /* don't suspend or resume card normally */
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev)) if (d3_delay < 20 && (rdev->px_quirk_flags & RADEON_PX_QUIRK_LONG_WAKEUP))
dev->pdev->d3_delay = 20; dev->pdev->d3_delay = 20;
radeon_resume_kms(dev, true, true); radeon_resume_kms(dev, true, true);
...@@ -1338,6 +1365,9 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -1338,6 +1365,9 @@ int radeon_device_init(struct radeon_device *rdev,
if (rdev->rio_mem == NULL) if (rdev->rio_mem == NULL)
DRM_ERROR("Unable to find PCI I/O BAR\n"); DRM_ERROR("Unable to find PCI I/O BAR\n");
if (rdev->flags & RADEON_IS_PX)
radeon_device_handle_px_quirks(rdev);
/* if we have > 1 VGA cards, then disable the radeon VGA resources */ /* if we have > 1 VGA cards, then disable the radeon VGA resources */
/* this will fail for cards that aren't VGA class devices, just /* this will fail for cards that aren't VGA class devices, just
* ignore it */ * ignore it */
......
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