Skip to content

Commit

Permalink
drm/i915: make sure VDD is turned off during system suspend
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Imre Deak authored and Jani Nikula committed Aug 18, 2014
1 parent 1d0d343 commit 07f9cd0
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
17 changes: 17 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,21 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
}

static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
struct drm_encoder *encoder;

drm_modeset_lock_all(dev);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);

if (intel_encoder->suspend)
intel_encoder->suspend(intel_encoder);
}
drm_modeset_unlock_all(dev);
}

static int i915_drm_freeze(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
Expand Down Expand Up @@ -555,6 +570,8 @@ static int i915_drm_freeze(struct drm_device *dev)
intel_runtime_pm_disable_interrupts(dev);
intel_hpd_cancel_work(dev_priv);

intel_suspend_encoders(dev_priv);

intel_suspend_gt_powersave(dev);

intel_modeset_suspend_hw(dev);
Expand Down
11 changes: 11 additions & 0 deletions drivers/gpu/drm/i915/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4003,6 +4003,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
kfree(intel_dig_port);
}

static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);

if (!is_edp(intel_dp))
return;

edp_panel_vdd_off_sync(intel_dp);
}

static void intel_dp_encoder_reset(struct drm_encoder *encoder)
{
intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder));
Expand Down Expand Up @@ -4731,6 +4741,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_encoder->disable = intel_disable_dp;
intel_encoder->get_hw_state = intel_dp_get_hw_state;
intel_encoder->get_config = intel_dp_get_config;
intel_encoder->suspend = intel_dp_encoder_suspend;
if (IS_CHERRYVIEW(dev)) {
intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
intel_encoder->pre_enable = chv_pre_enable_dp;
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ struct intel_encoder {
* be set correctly before calling this function. */
void (*get_config)(struct intel_encoder *,
struct intel_crtc_config *pipe_config);
/*
* Called during system suspend after all pending requests for the
* encoder are flushed (for example for DP AUX transactions) and
* device interrupts are disabled.
*/
void (*suspend)(struct intel_encoder *);
int crtc_mask;
enum hpd_pin hpd_pin;
};
Expand Down

0 comments on commit 07f9cd0

Please sign in to comment.