|
@@ -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 */
|