Closes: https://issues.redhat.com/browse/RHEL-120913
Signed-off-by: Arun R Murthy <[email protected]>
---
drivers/gpu/drm/i915/display/intel_dp.c | 41 +++++++++++++++++++
drivers/gpu/drm/i915/display/intel_dp.h | 1 +
.../drm/i915/display/intel_dp_link_training.c | 3 ++
3 files changed, 45 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
b/drivers/gpu/drm/i915/display/intel_dp.c
index 454e6144ee4e..2fbb947e6cc8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4705,6 +4705,45 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp)
intel_edp_set_data_override_rates(intel_dp);
}
+void intel_dp_wake_sink(struct intel_dp *intel_dp)
+{
+ u8 value = 0;
+ int ret = 0, try = 0;
+
+ intel_dp_dpcd_set_probe(intel_dp, false);
+
+ /*
+ * Wake the sink device
+ * Spec DP2.1 section 2.3.1.2 if AUX CH is powered down by writing 0x02
+ * to DP_SET_POWER dpcd reg, 1ms time would be required to wake it up
+ */
+ while (try < 10 && ret < 0) {
+ ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_SET_POWER, &value);
+ /*
+ * If sink is in D3 then it may not respond to the AUX tx so
+ * wake it up to D3_AUX_ON state
+ */
+ if (value == DP_SET_POWER_D3) {
+ /* After setting to D0 need a min of 1ms to wake(Spec
DP2.1 sec 2.3.1.2) */
+ drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER,
+ DP_SET_POWER_D0);
+ fsleep(1000);
+ drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER,
+ DP_SET_POWER_D3_AUX_ON);
+ break;
+ } else if ((value == DP_SET_POWER_D0) ||
+ (value == DP_SET_POWER_D3_AUX_ON)) {
+ /* if in D0 or D3_AUX_ON exit */
+ break;
+ }
+ /* Sink in D0 or even if read fails a minimum of 1ms is
required to wake and respond */
+ fsleep(1000);
+ try++;
+ }
+
+ intel_dp_dpcd_set_probe(intel_dp, true);
+}
+
static bool
intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector
*connector)
{
@@ -4713,6 +4752,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct
intel_connector *connector
/* this function is meant to be called only once */
drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0);
+ intel_dp_wake_sink(intel_dp);
+
if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd) != 0)
return false;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index b0bbd5981f57..3f16077c0cc7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -232,6 +232,7 @@ bool intel_dp_dotclk_valid(struct intel_display *display,
bool intel_dp_joiner_candidate_valid(struct intel_connector *connector,
int hdisplay,
int num_joined_pipes);
+void intel_dp_wake_sink(struct intel_dp *intel_dp);
#define for_each_joiner_candidate(__connector, __mode, __num_joined_pipes) \
for ((__num_joined_pipes) = 1; (__num_joined_pipes) <=
(I915_MAX_PIPES); (__num_joined_pipes)++) \
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 54c585c59b90..cbb712ea9f60 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -270,6 +270,9 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp
*intel_dp)
lttpr_count = intel_dp_init_lttpr(intel_dp, dpcd);
}
+ /* After reading LTTPR wake up the sink before reading DPRX caps */
+ intel_dp_wake_sink(intel_dp);
+
/*
* The DPTX shall read the DPRX caps after LTTPR detection, so re-read
* it here.
--
2.25.1