diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2014-07-18 11:54:20 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2014-08-05 08:53:36 -0400 |
commit | 4807c5a8a0c87a210c36e3ad74c451a909d88588 (patch) | |
tree | 0e786a121073e3e3e3491838f60e7eaecf95bf2b | |
parent | 391bfec33cd4e103274f197924d41ef648b849de (diff) |
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 <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 1 | ||||
-rw-r--r-- | 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 { | |||
2353 | 2353 | ||
2354 | struct dev_pm_domain vga_pm_domain; | 2354 | struct dev_pm_domain vga_pm_domain; |
2355 | bool have_disp_power_ref; | 2355 | bool have_disp_power_ref; |
2356 | u32 px_quirk_flags; | ||
2356 | 2357 | ||
2357 | /* tracking pinned memory */ | 2358 | /* tracking pinned memory */ |
2358 | u64 vram_pin_size; | 2359 | 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] = { | |||
103 | "LAST", | 103 | "LAST", |
104 | }; | 104 | }; |
105 | 105 | ||
106 | #define RADEON_PX_QUIRK_DISABLE_PX (1 << 0) | ||
107 | #define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1) | ||
108 | |||
109 | struct radeon_px_quirk { | ||
110 | u32 chip_vendor; | ||
111 | u32 chip_device; | ||
112 | u32 subsys_vendor; | ||
113 | u32 subsys_device; | ||
114 | u32 px_quirk_flags; | ||
115 | }; | ||
116 | |||
117 | static struct radeon_px_quirk radeon_px_quirk_list[] = { | ||
118 | /* Acer aspire 5560g (CPU: AMD A4-3305M; GPU: AMD Radeon HD 6480g + 7470m) | ||
119 | * https://bugzilla.kernel.org/show_bug.cgi?id=74551 | ||
120 | */ | ||
121 | { PCI_VENDOR_ID_ATI, 0x6760, 0x1025, 0x0672, RADEON_PX_QUIRK_DISABLE_PX }, | ||
122 | /* Asus K73TA laptop with AMD A6-3400M APU and Radeon 6550 GPU | ||
123 | * https://bugzilla.kernel.org/show_bug.cgi?id=51381 | ||
124 | */ | ||
125 | { PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x108c, RADEON_PX_QUIRK_DISABLE_PX }, | ||
126 | /* macbook pro 8.2 */ | ||
127 | { PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP }, | ||
128 | { 0, 0, 0, 0, 0 }, | ||
129 | }; | ||
130 | |||
106 | bool radeon_is_px(struct drm_device *dev) | 131 | bool radeon_is_px(struct drm_device *dev) |
107 | { | 132 | { |
108 | struct radeon_device *rdev = dev->dev_private; | 133 | struct radeon_device *rdev = dev->dev_private; |
@@ -112,6 +137,26 @@ bool radeon_is_px(struct drm_device *dev) | |||
112 | return false; | 137 | return false; |
113 | } | 138 | } |
114 | 139 | ||
140 | static void radeon_device_handle_px_quirks(struct radeon_device *rdev) | ||
141 | { | ||
142 | struct radeon_px_quirk *p = radeon_px_quirk_list; | ||
143 | |||
144 | /* Apply PX quirks */ | ||
145 | while (p && p->chip_device != 0) { | ||
146 | if (rdev->pdev->vendor == p->chip_vendor && | ||
147 | rdev->pdev->device == p->chip_device && | ||
148 | rdev->pdev->subsystem_vendor == p->subsys_vendor && | ||
149 | rdev->pdev->subsystem_device == p->subsys_device) { | ||
150 | rdev->px_quirk_flags = p->px_quirk_flags; | ||
151 | break; | ||
152 | } | ||
153 | ++p; | ||
154 | } | ||
155 | |||
156 | if (rdev->px_quirk_flags & RADEON_PX_QUIRK_DISABLE_PX) | ||
157 | rdev->flags &= ~RADEON_IS_PX; | ||
158 | } | ||
159 | |||
115 | /** | 160 | /** |
116 | * radeon_program_register_sequence - program an array of registers. | 161 | * radeon_program_register_sequence - program an array of registers. |
117 | * | 162 | * |
@@ -1093,25 +1138,6 @@ static void radeon_check_arguments(struct radeon_device *rdev) | |||
1093 | } | 1138 | } |
1094 | 1139 | ||
1095 | /** | 1140 | /** |
1096 | * radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is | ||
1097 | * needed for waking up. | ||
1098 | * | ||
1099 | * @pdev: pci dev pointer | ||
1100 | */ | ||
1101 | static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev) | ||
1102 | { | ||
1103 | |||
1104 | /* 6600m in a macbook pro */ | ||
1105 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && | ||
1106 | pdev->subsystem_device == 0x00e2) { | ||
1107 | printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n"); | ||
1108 | return true; | ||
1109 | } | ||
1110 | |||
1111 | return false; | ||
1112 | } | ||
1113 | |||
1114 | /** | ||
1115 | * radeon_switcheroo_set_state - set switcheroo state | 1141 | * radeon_switcheroo_set_state - set switcheroo state |
1116 | * | 1142 | * |
1117 | * @pdev: pci dev pointer | 1143 | * @pdev: pci dev pointer |
@@ -1123,6 +1149,7 @@ static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev) | |||
1123 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) | 1149 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) |
1124 | { | 1150 | { |
1125 | struct drm_device *dev = pci_get_drvdata(pdev); | 1151 | struct drm_device *dev = pci_get_drvdata(pdev); |
1152 | struct radeon_device *rdev = dev->dev_private; | ||
1126 | 1153 | ||
1127 | if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) | 1154 | if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) |
1128 | return; | 1155 | return; |
@@ -1134,7 +1161,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero | |||
1134 | /* don't suspend or resume card normally */ | 1161 | /* don't suspend or resume card normally */ |
1135 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | 1162 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; |
1136 | 1163 | ||
1137 | if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev)) | 1164 | if (d3_delay < 20 && (rdev->px_quirk_flags & RADEON_PX_QUIRK_LONG_WAKEUP)) |
1138 | dev->pdev->d3_delay = 20; | 1165 | dev->pdev->d3_delay = 20; |
1139 | 1166 | ||
1140 | radeon_resume_kms(dev, true, true); | 1167 | radeon_resume_kms(dev, true, true); |
@@ -1338,6 +1365,9 @@ int radeon_device_init(struct radeon_device *rdev, | |||
1338 | if (rdev->rio_mem == NULL) | 1365 | if (rdev->rio_mem == NULL) |
1339 | DRM_ERROR("Unable to find PCI I/O BAR\n"); | 1366 | DRM_ERROR("Unable to find PCI I/O BAR\n"); |
1340 | 1367 | ||
1368 | if (rdev->flags & RADEON_IS_PX) | ||
1369 | radeon_device_handle_px_quirks(rdev); | ||
1370 | |||
1341 | /* if we have > 1 VGA cards, then disable the radeon VGA resources */ | 1371 | /* if we have > 1 VGA cards, then disable the radeon VGA resources */ |
1342 | /* this will fail for cards that aren't VGA class devices, just | 1372 | /* this will fail for cards that aren't VGA class devices, just |
1343 | * ignore it */ | 1373 | * ignore it */ |