From 4807c5a8a0c87a210c36e3ad74c451a909d88588 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 18 Jul 2014 11:54:20 -0400 Subject: [PATCH] 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=74551 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_device.c | 70 ++++++++++++++++++-------- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f9ffd98aa6a4..8d0ce11ef47b 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2353,6 +2353,7 @@ struct radeon_device { struct dev_pm_domain vga_pm_domain; bool have_disp_power_ref; + u32 px_quirk_flags; /* tracking pinned memory */ u64 vram_pin_size; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 61990bda285d..248bce86af51 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -103,6 +103,31 @@ static const char radeon_family_name[][16] = { "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) { struct radeon_device *rdev = dev->dev_private; @@ -112,6 +137,26 @@ bool radeon_is_px(struct drm_device *dev) 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. * @@ -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 * @@ -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) { struct drm_device *dev = pci_get_drvdata(pdev); + struct radeon_device *rdev = dev->dev_private; if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) return; @@ -1134,7 +1161,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero /* don't suspend or resume card normally */ 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; radeon_resume_kms(dev, true, true); @@ -1338,6 +1365,9 @@ int radeon_device_init(struct radeon_device *rdev, if (rdev->rio_mem == NULL) 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 */ /* this will fail for cards that aren't VGA class devices, just * ignore it */ -- 2.39.5