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

Commit cc3054ff authored by José Roberto de Souza's avatar José Roberto de Souza Committed by Dhinakaran Pandiyan
Browse files

drm/i915/psr: Begin to handle PSR/PSR2 errors set by sink



eDP spec states that sink device will do a short pulse in HPD
line when there is a PSR/PSR2 error that needs to be handled by
source, this is handling the first and most simples error:
DP_PSR_SINK_INTERNAL_ERROR.

Here taking the safest approach and disabling PSR(at least until
the next modeset), to avoid multiple rendering issues due to
bad pannels.

v5:
added lockdep_assert in psr_disable and renamed psr_disable()
to intel_psr_disable_locked()

v4:
Using CAN_PSR instead of HAS_PSR in intel_psr_short_pulse

v3:
disabling PSR instead of exiting on error

Reviewed-by: default avatarDhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: default avatarJosé Roberto de Souza <jose.souza@intel.com>
Signed-off-by: default avatarDhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180626201644.21932-2-jose.souza@intel.com
parent 42f53ffc
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4491,6 +4491,8 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
	if (intel_dp_needs_link_retrain(intel_dp))
		return false;

	intel_psr_short_pulse(intel_dp);

	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
		DRM_DEBUG_KMS("Link Training Compliance Test requested\n");
		/* Send a Hotplug Uevent to userspace to start modeset */
+1 −0
Original line number Diff line number Diff line
@@ -1920,6 +1920,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
			      struct intel_crtc_state *crtc_state);
void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool debug);
void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir);
void intel_psr_short_pulse(struct intel_dp *intel_dp);

/* intel_runtime_pm.c */
int intel_power_domains_init(struct drm_i915_private *);
+51 −11
Original line number Diff line number Diff line
@@ -666,6 +666,25 @@ intel_psr_disable_source(struct intel_dp *intel_dp)
	}
}

static void intel_psr_disable_locked(struct intel_dp *intel_dp)
{
	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
	struct drm_device *dev = intel_dig_port->base.base.dev;
	struct drm_i915_private *dev_priv = to_i915(dev);

	lockdep_assert_held(&dev_priv->psr.lock);

	if (!dev_priv->psr.enabled)
		return;

	intel_psr_disable_source(intel_dp);

	/* Disable PSR on Sink */
	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);

	dev_priv->psr.enabled = NULL;
}

/**
 * intel_psr_disable - Disable PSR
 * @intel_dp: Intel DP
@@ -687,17 +706,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
		return;

	mutex_lock(&dev_priv->psr.lock);
	if (!dev_priv->psr.enabled) {
		mutex_unlock(&dev_priv->psr.lock);
		return;
	}

	intel_psr_disable_source(intel_dp);

	/* Disable PSR on Sink */
	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);

	dev_priv->psr.enabled = NULL;
	intel_psr_disable_locked(intel_dp);
	mutex_unlock(&dev_priv->psr.lock);
	cancel_work_sync(&dev_priv->psr.work);
}
@@ -932,3 +941,34 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
	INIT_WORK(&dev_priv->psr.work, intel_psr_work);
	mutex_init(&dev_priv->psr.lock);
}

void intel_psr_short_pulse(struct intel_dp *intel_dp)
{
	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
	struct drm_device *dev = intel_dig_port->base.base.dev;
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct i915_psr *psr = &dev_priv->psr;
	u8 val;

	if (!CAN_PSR(dev_priv) || !intel_dp_is_edp(intel_dp))
		return;

	mutex_lock(&psr->lock);

	if (psr->enabled != intel_dp)
		goto exit;

	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val) != 1) {
		DRM_ERROR("PSR_STATUS dpcd read failed\n");
		goto exit;
	}

	if ((val & DP_PSR_SINK_STATE_MASK) == DP_PSR_SINK_INTERNAL_ERROR) {
		DRM_DEBUG_KMS("PSR sink internal error, disabling PSR\n");
		intel_psr_disable_locked(intel_dp);
	}

	/* TODO: handle other PSR/PSR2 errors */
exit:
	mutex_unlock(&psr->lock);
}