Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07f9cd0b authored by Imre Deak's avatar Imre Deak Committed by Jani Nikula
Browse files

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: default avatarImre 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: default avatarJani Nikula <jani.nikula@intel.com>
parent 1d0d343a
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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);
+11 −0
Original line number Diff line number Diff line
@@ -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));
@@ -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;
+6 −0
Original line number Diff line number Diff line
@@ -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;
};