diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ccbdd83f5220..b0e4a0bd1313 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -5063,8 +5063,26 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) | |||
5063 | } | 5063 | } |
5064 | } else { | 5064 | } else { |
5065 | if (enable_requested) { | 5065 | if (enable_requested) { |
5066 | unsigned long irqflags; | ||
5067 | enum pipe p; | ||
5068 | |||
5066 | I915_WRITE(HSW_PWR_WELL_DRIVER, 0); | 5069 | I915_WRITE(HSW_PWR_WELL_DRIVER, 0); |
5070 | POSTING_READ(HSW_PWR_WELL_DRIVER); | ||
5067 | DRM_DEBUG_KMS("Requesting to disable the power well\n"); | 5071 | DRM_DEBUG_KMS("Requesting to disable the power well\n"); |
5072 | |||
5073 | /* | ||
5074 | * After this, the registers on the pipes that are part | ||
5075 | * of the power well will become zero, so we have to | ||
5076 | * adjust our counters according to that. | ||
5077 | * | ||
5078 | * FIXME: Should we do this in general in | ||
5079 | * drm_vblank_post_modeset? | ||
5080 | */ | ||
5081 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | ||
5082 | for_each_pipe(p) | ||
5083 | if (p != PIPE_A) | ||
5084 | dev->last_vblank[p] = 0; | ||
5085 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | ||
5068 | } | 5086 | } |
5069 | } | 5087 | } |
5070 | } | 5088 | } |
@@ -5476,7 +5494,7 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv) | |||
5476 | gen6_gt_check_fifodbg(dev_priv); | 5494 | gen6_gt_check_fifodbg(dev_priv); |
5477 | } | 5495 | } |
5478 | 5496 | ||
5479 | void intel_gt_reset(struct drm_device *dev) | 5497 | void intel_gt_sanitize(struct drm_device *dev) |
5480 | { | 5498 | { |
5481 | struct drm_i915_private *dev_priv = dev->dev_private; | 5499 | struct drm_i915_private *dev_priv = dev->dev_private; |
5482 | 5500 | ||
@@ -5487,26 +5505,61 @@ void intel_gt_reset(struct drm_device *dev) | |||
5487 | if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) | 5505 | if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) |
5488 | __gen6_gt_force_wake_mt_reset(dev_priv); | 5506 | __gen6_gt_force_wake_mt_reset(dev_priv); |
5489 | } | 5507 | } |
5508 | |||
5509 | /* BIOS often leaves RC6 enabled, but disable it for hw init */ | ||
5510 | if (INTEL_INFO(dev)->gen >= 6) | ||
5511 | intel_disable_gt_powersave(dev); | ||
5490 | } | 5512 | } |
5491 | 5513 | ||
5492 | void intel_gt_init(struct drm_device *dev) | 5514 | void intel_gt_init(struct drm_device *dev) |
5493 | { | 5515 | { |
5494 | struct drm_i915_private *dev_priv = dev->dev_private; | 5516 | struct drm_i915_private *dev_priv = dev->dev_private; |
5495 | 5517 | ||
5496 | spin_lock_init(&dev_priv->gt_lock); | ||
5497 | |||
5498 | intel_gt_reset(dev); | ||
5499 | |||
5500 | if (IS_VALLEYVIEW(dev)) { | 5518 | if (IS_VALLEYVIEW(dev)) { |
5501 | dev_priv->gt.force_wake_get = vlv_force_wake_get; | 5519 | dev_priv->gt.force_wake_get = vlv_force_wake_get; |
5502 | dev_priv->gt.force_wake_put = vlv_force_wake_put; | 5520 | dev_priv->gt.force_wake_put = vlv_force_wake_put; |
5503 | } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { | 5521 | } else if (IS_HASWELL(dev)) { |
5504 | dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get; | 5522 | dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get; |
5505 | dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put; | 5523 | dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put; |
5524 | } else if (IS_IVYBRIDGE(dev)) { | ||
5525 | u32 ecobus; | ||
5526 | |||
5527 | /* IVB configs may use multi-threaded forcewake */ | ||
5528 | |||
5529 | /* A small trick here - if the bios hasn't configured | ||
5530 | * MT forcewake, and if the device is in RC6, then | ||
5531 | * force_wake_mt_get will not wake the device and the | ||
5532 | * ECOBUS read will return zero. Which will be | ||
5533 | * (correctly) interpreted by the test below as MT | ||
5534 | * forcewake being disabled. | ||
5535 | */ | ||
5536 | mutex_lock(&dev->struct_mutex); | ||
5537 | __gen6_gt_force_wake_mt_get(dev_priv); | ||
5538 | ecobus = I915_READ_NOTRACE(ECOBUS); | ||
5539 | __gen6_gt_force_wake_mt_put(dev_priv); | ||
5540 | mutex_unlock(&dev->struct_mutex); | ||
5541 | |||
5542 | if (ecobus & FORCEWAKE_MT_ENABLE) { | ||
5543 | dev_priv->gt.force_wake_get = | ||
5544 | __gen6_gt_force_wake_mt_get; | ||
5545 | dev_priv->gt.force_wake_put = | ||
5546 | __gen6_gt_force_wake_mt_put; | ||
5547 | } else { | ||
5548 | DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n"); | ||
5549 | DRM_INFO("when using vblank-synced partial screen updates.\n"); | ||
5550 | dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; | ||
5551 | dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; | ||
5552 | } | ||
5506 | } else if (IS_GEN6(dev)) { | 5553 | } else if (IS_GEN6(dev)) { |
5507 | dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; | 5554 | dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; |
5508 | dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; | 5555 | dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; |
5509 | } | 5556 | } |
5557 | } | ||
5558 | |||
5559 | void intel_pm_init(struct drm_device *dev) | ||
5560 | { | ||
5561 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
5562 | |||
5510 | INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, | 5563 | INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, |
5511 | intel_gen6_powersave_work); | 5564 | intel_gen6_powersave_work); |
5512 | } | 5565 | } |