mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
1d0d343abb
commit
07f9cd0b38
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue