diff options
author | Imre Deak <imre.deak@intel.com> | 2014-08-18 07:42:45 -0400 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2014-08-18 09:49:36 -0400 |
commit | 07f9cd0b3870e306ddc5abcc3af2d748c9bd378c (patch) | |
tree | 7facf7045d5be69199077786fe4dd633b441c3e6 /drivers | |
parent | 1d0d343abb70922adebebc1cfcef6622f4c7edec (diff) |
drm/i915: make sure VDD is turned off during system suspend
Atm we may leave eDP VDD enabled during system suspend after the CRTCs
are disabled through an HPD->DPCD read event. So disable VDD during
suspend at a point when no HPDs can occur.
Note that runtime suspend doesn't have the same problem, since there the
RPM ref held by VDD provides already the needed serialization.
v2:
- add note to commit message about the runtime suspend path (Ville)
- use edp_panel_vdd_off_sync(), so we can keep the WARN in
edp_panel_vdd_off() (Ville)
v3:
- rebased on -fixes (for_each_intel_encoder()->list_for_each_entry())
(Imre)
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> (v2)
Cc: stable@vger.kernel.org (3.16+)
[Jani: fix sparse warning reported by Fengguang Wu]
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 6 |
3 files changed, 34 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3f9c8f6b2418..e27cdbe9d524 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -509,6 +509,21 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) | |||
509 | cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work); | 509 | cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work); |
510 | } | 510 | } |
511 | 511 | ||
512 | static void intel_suspend_encoders(struct drm_i915_private *dev_priv) | ||
513 | { | ||
514 | struct drm_device *dev = dev_priv->dev; | ||
515 | struct drm_encoder *encoder; | ||
516 | |||
517 | drm_modeset_lock_all(dev); | ||
518 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
519 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); | ||
520 | |||
521 | if (intel_encoder->suspend) | ||
522 | intel_encoder->suspend(intel_encoder); | ||
523 | } | ||
524 | drm_modeset_unlock_all(dev); | ||
525 | } | ||
526 | |||
512 | static int i915_drm_freeze(struct drm_device *dev) | 527 | static int i915_drm_freeze(struct drm_device *dev) |
513 | { | 528 | { |
514 | struct drm_i915_private *dev_priv = dev->dev_private; | 529 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -555,6 +570,8 @@ static int i915_drm_freeze(struct drm_device *dev) | |||
555 | intel_runtime_pm_disable_interrupts(dev); | 570 | intel_runtime_pm_disable_interrupts(dev); |
556 | intel_hpd_cancel_work(dev_priv); | 571 | intel_hpd_cancel_work(dev_priv); |
557 | 572 | ||
573 | intel_suspend_encoders(dev_priv); | ||
574 | |||
558 | intel_suspend_gt_powersave(dev); | 575 | intel_suspend_gt_powersave(dev); |
559 | 576 | ||
560 | intel_modeset_suspend_hw(dev); | 577 | intel_modeset_suspend_hw(dev); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a520188e6d97..39b643163846 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -4003,6 +4003,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) | |||
4003 | kfree(intel_dig_port); | 4003 | kfree(intel_dig_port); |
4004 | } | 4004 | } |
4005 | 4005 | ||
4006 | static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) | ||
4007 | { | ||
4008 | struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); | ||
4009 | |||
4010 | if (!is_edp(intel_dp)) | ||
4011 | return; | ||
4012 | |||
4013 | edp_panel_vdd_off_sync(intel_dp); | ||
4014 | } | ||
4015 | |||
4006 | static void intel_dp_encoder_reset(struct drm_encoder *encoder) | 4016 | static void intel_dp_encoder_reset(struct drm_encoder *encoder) |
4007 | { | 4017 | { |
4008 | intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); | 4018 | intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); |
@@ -4731,6 +4741,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) | |||
4731 | intel_encoder->disable = intel_disable_dp; | 4741 | intel_encoder->disable = intel_disable_dp; |
4732 | intel_encoder->get_hw_state = intel_dp_get_hw_state; | 4742 | intel_encoder->get_hw_state = intel_dp_get_hw_state; |
4733 | intel_encoder->get_config = intel_dp_get_config; | 4743 | intel_encoder->get_config = intel_dp_get_config; |
4744 | intel_encoder->suspend = intel_dp_encoder_suspend; | ||
4734 | if (IS_CHERRYVIEW(dev)) { | 4745 | if (IS_CHERRYVIEW(dev)) { |
4735 | intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; | 4746 | intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; |
4736 | intel_encoder->pre_enable = chv_pre_enable_dp; | 4747 | intel_encoder->pre_enable = chv_pre_enable_dp; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index fe3431f96900..b8c8bbd8e5f9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -153,6 +153,12 @@ struct intel_encoder { | |||
153 | * be set correctly before calling this function. */ | 153 | * be set correctly before calling this function. */ |
154 | void (*get_config)(struct intel_encoder *, | 154 | void (*get_config)(struct intel_encoder *, |
155 | struct intel_crtc_config *pipe_config); | 155 | struct intel_crtc_config *pipe_config); |
156 | /* | ||
157 | * Called during system suspend after all pending requests for the | ||
158 | * encoder are flushed (for example for DP AUX transactions) and | ||
159 | * device interrupts are disabled. | ||
160 | */ | ||
161 | void (*suspend)(struct intel_encoder *); | ||
156 | int crtc_mask; | 162 | int crtc_mask; |
157 | enum hpd_pin hpd_pin; | 163 | enum hpd_pin hpd_pin; |
158 | }; | 164 | }; |