diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 49b06590001e..edfc54e41842 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -897,6 +897,25 @@ static void radeon_check_arguments(struct radeon_device *rdev) | |||
897 | } | 897 | } |
898 | 898 | ||
899 | /** | 899 | /** |
900 | * radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is | ||
901 | * needed for waking up. | ||
902 | * | ||
903 | * @pdev: pci dev pointer | ||
904 | */ | ||
905 | static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev) | ||
906 | { | ||
907 | |||
908 | /* 6600m in a macbook pro */ | ||
909 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && | ||
910 | pdev->subsystem_device == 0x00e2) { | ||
911 | printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n"); | ||
912 | return true; | ||
913 | } | ||
914 | |||
915 | return false; | ||
916 | } | ||
917 | |||
918 | /** | ||
900 | * radeon_switcheroo_set_state - set switcheroo state | 919 | * radeon_switcheroo_set_state - set switcheroo state |
901 | * | 920 | * |
902 | * @pdev: pci dev pointer | 921 | * @pdev: pci dev pointer |
@@ -910,10 +929,19 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero | |||
910 | struct drm_device *dev = pci_get_drvdata(pdev); | 929 | struct drm_device *dev = pci_get_drvdata(pdev); |
911 | pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; | 930 | pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; |
912 | if (state == VGA_SWITCHEROO_ON) { | 931 | if (state == VGA_SWITCHEROO_ON) { |
932 | unsigned d3_delay = dev->pdev->d3_delay; | ||
933 | |||
913 | printk(KERN_INFO "radeon: switched on\n"); | 934 | printk(KERN_INFO "radeon: switched on\n"); |
914 | /* don't suspend or resume card normally */ | 935 | /* don't suspend or resume card normally */ |
915 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | 936 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; |
937 | |||
938 | if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev)) | ||
939 | dev->pdev->d3_delay = 20; | ||
940 | |||
916 | radeon_resume_kms(dev); | 941 | radeon_resume_kms(dev); |
942 | |||
943 | dev->pdev->d3_delay = d3_delay; | ||
944 | |||
917 | dev->switch_power_state = DRM_SWITCH_POWER_ON; | 945 | dev->switch_power_state = DRM_SWITCH_POWER_ON; |
918 | drm_kms_helper_poll_enable(dev); | 946 | drm_kms_helper_poll_enable(dev); |
919 | } else { | 947 | } else { |
@@ -1164,6 +1192,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
1164 | struct drm_crtc *crtc; | 1192 | struct drm_crtc *crtc; |
1165 | struct drm_connector *connector; | 1193 | struct drm_connector *connector; |
1166 | int i, r; | 1194 | int i, r; |
1195 | bool force_completion = false; | ||
1167 | 1196 | ||
1168 | if (dev == NULL || dev->dev_private == NULL) { | 1197 | if (dev == NULL || dev->dev_private == NULL) { |
1169 | return -ENODEV; | 1198 | return -ENODEV; |
@@ -1206,8 +1235,16 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
1206 | 1235 | ||
1207 | mutex_lock(&rdev->ring_lock); | 1236 | mutex_lock(&rdev->ring_lock); |
1208 | /* wait for gpu to finish processing current batch */ | 1237 | /* wait for gpu to finish processing current batch */ |
1209 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 1238 | for (i = 0; i < RADEON_NUM_RINGS; i++) { |
1210 | radeon_fence_wait_empty_locked(rdev, i); | 1239 | r = radeon_fence_wait_empty_locked(rdev, i); |
1240 | if (r) { | ||
1241 | /* delay GPU reset to resume */ | ||
1242 | force_completion = true; | ||
1243 | } | ||
1244 | } | ||
1245 | if (force_completion) { | ||
1246 | radeon_fence_driver_force_completion(rdev); | ||
1247 | } | ||
1211 | mutex_unlock(&rdev->ring_lock); | 1248 | mutex_unlock(&rdev->ring_lock); |
1212 | 1249 | ||
1213 | radeon_save_bios_scratch_regs(rdev); | 1250 | radeon_save_bios_scratch_regs(rdev); |
@@ -1338,7 +1375,6 @@ retry: | |||
1338 | } | 1375 | } |
1339 | 1376 | ||
1340 | radeon_restore_bios_scratch_regs(rdev); | 1377 | radeon_restore_bios_scratch_regs(rdev); |
1341 | drm_helper_resume_force_mode(rdev->ddev); | ||
1342 | 1378 | ||
1343 | if (!r) { | 1379 | if (!r) { |
1344 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 1380 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
@@ -1358,11 +1394,14 @@ retry: | |||
1358 | } | 1394 | } |
1359 | } | 1395 | } |
1360 | } else { | 1396 | } else { |
1397 | radeon_fence_driver_force_completion(rdev); | ||
1361 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 1398 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
1362 | kfree(ring_data[i]); | 1399 | kfree(ring_data[i]); |
1363 | } | 1400 | } |
1364 | } | 1401 | } |
1365 | 1402 | ||
1403 | drm_helper_resume_force_mode(rdev->ddev); | ||
1404 | |||
1366 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | 1405 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); |
1367 | if (r) { | 1406 | if (r) { |
1368 | /* bad news, how to tell it to userspace ? */ | 1407 | /* bad news, how to tell it to userspace ? */ |