aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 8039cec71fc2..5c66b568bb81 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -622,7 +622,7 @@ static int i915_drm_suspend(struct drm_device *dev)
622 return 0; 622 return 0;
623} 623}
624 624
625static int i915_drm_suspend_late(struct drm_device *drm_dev) 625static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
626{ 626{
627 struct drm_i915_private *dev_priv = drm_dev->dev_private; 627 struct drm_i915_private *dev_priv = drm_dev->dev_private;
628 int ret; 628 int ret;
@@ -636,7 +636,17 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev)
636 } 636 }
637 637
638 pci_disable_device(drm_dev->pdev); 638 pci_disable_device(drm_dev->pdev);
639 pci_set_power_state(drm_dev->pdev, PCI_D3hot); 639 /*
640 * During hibernation on some GEN4 platforms the BIOS may try to access
641 * the device even though it's already in D3 and hang the machine. So
642 * leave the device in D0 on those platforms and hope the BIOS will
643 * power down the device properly. Platforms where this was seen:
644 * Lenovo Thinkpad X301, X61s
645 */
646 if (!(hibernation &&
647 drm_dev->pdev->subsystem_vendor == PCI_VENDOR_ID_LENOVO &&
648 INTEL_INFO(dev_priv)->gen == 4))
649 pci_set_power_state(drm_dev->pdev, PCI_D3hot);
640 650
641 return 0; 651 return 0;
642} 652}
@@ -662,7 +672,7 @@ int i915_suspend_legacy(struct drm_device *dev, pm_message_t state)
662 if (error) 672 if (error)
663 return error; 673 return error;
664 674
665 return i915_drm_suspend_late(dev); 675 return i915_drm_suspend_late(dev, false);
666} 676}
667 677
668static int i915_drm_resume(struct drm_device *dev) 678static int i915_drm_resume(struct drm_device *dev)
@@ -950,7 +960,17 @@ static int i915_pm_suspend_late(struct device *dev)
950 if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) 960 if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
951 return 0; 961 return 0;
952 962
953 return i915_drm_suspend_late(drm_dev); 963 return i915_drm_suspend_late(drm_dev, false);
964}
965
966static int i915_pm_poweroff_late(struct device *dev)
967{
968 struct drm_device *drm_dev = dev_to_i915(dev)->dev;
969
970 if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
971 return 0;
972
973 return i915_drm_suspend_late(drm_dev, true);
954} 974}
955 975
956static int i915_pm_resume_early(struct device *dev) 976static int i915_pm_resume_early(struct device *dev)
@@ -1075,6 +1095,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
1075 /* Gunit-Display CZ domain, 0x182028-0x1821CF */ 1095 /* Gunit-Display CZ domain, 0x182028-0x1821CF */
1076 s->gu_ctl0 = I915_READ(VLV_GU_CTL0); 1096 s->gu_ctl0 = I915_READ(VLV_GU_CTL0);
1077 s->gu_ctl1 = I915_READ(VLV_GU_CTL1); 1097 s->gu_ctl1 = I915_READ(VLV_GU_CTL1);
1098 s->pcbr = I915_READ(VLV_PCBR);
1078 s->clock_gate_dis2 = I915_READ(VLV_GUNIT_CLOCK_GATE2); 1099 s->clock_gate_dis2 = I915_READ(VLV_GUNIT_CLOCK_GATE2);
1079 1100
1080 /* 1101 /*
@@ -1169,6 +1190,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
1169 /* Gunit-Display CZ domain, 0x182028-0x1821CF */ 1190 /* Gunit-Display CZ domain, 0x182028-0x1821CF */
1170 I915_WRITE(VLV_GU_CTL0, s->gu_ctl0); 1191 I915_WRITE(VLV_GU_CTL0, s->gu_ctl0);
1171 I915_WRITE(VLV_GU_CTL1, s->gu_ctl1); 1192 I915_WRITE(VLV_GU_CTL1, s->gu_ctl1);
1193 I915_WRITE(VLV_PCBR, s->pcbr);
1172 I915_WRITE(VLV_GUNIT_CLOCK_GATE2, s->clock_gate_dis2); 1194 I915_WRITE(VLV_GUNIT_CLOCK_GATE2, s->clock_gate_dis2);
1173} 1195}
1174 1196
@@ -1177,19 +1199,7 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
1177 u32 val; 1199 u32 val;
1178 int err; 1200 int err;
1179 1201
1180 val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
1181 WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on);
1182
1183#define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT) 1202#define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
1184 /* Wait for a previous force-off to settle */
1185 if (force_on) {
1186 err = wait_for(!COND, 20);
1187 if (err) {
1188 DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
1189 I915_READ(VLV_GTLC_SURVIVABILITY_REG));
1190 return err;
1191 }
1192 }
1193 1203
1194 val = I915_READ(VLV_GTLC_SURVIVABILITY_REG); 1204 val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
1195 val &= ~VLV_GFX_CLK_FORCE_ON_BIT; 1205 val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
@@ -1520,7 +1530,7 @@ static const struct dev_pm_ops i915_pm_ops = {
1520 .thaw_early = i915_pm_resume_early, 1530 .thaw_early = i915_pm_resume_early,
1521 .thaw = i915_pm_resume, 1531 .thaw = i915_pm_resume,
1522 .poweroff = i915_pm_suspend, 1532 .poweroff = i915_pm_suspend,
1523 .poweroff_late = i915_pm_suspend_late, 1533 .poweroff_late = i915_pm_poweroff_late,
1524 .restore_early = i915_pm_resume_early, 1534 .restore_early = i915_pm_resume_early,
1525 .restore = i915_pm_resume, 1535 .restore = i915_pm_resume,
1526 1536