@@ -1280,6 +1280,7 @@ struct intel_dp {
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
+ u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
u8 fec_capable;
/* source rates */
int num_source_rates;
@@ -4721,6 +4721,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
{
int ret;
+ if (!intel_dp_is_edp(intel_dp))
+ intel_dp_read_lttpr_caps(intel_dp);
+
if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd))
return false;
@@ -50,6 +50,24 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATU
DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
}
+/**
+ * intel_dp_read_lttpr_caps - read the LTTPR common capabilities
+ * @intel_dp: Intel DP struct
+ *
+ * Read the LTTPR common capabilities.
+ */
+void intel_dp_read_lttpr_caps(struct intel_dp *intel_dp)
+{
+ if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
+ intel_dp->lttpr_common_caps) < 0)
+ return;
+
+ drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
+ "LTTPR common capabilities: %*ph\n",
+ (int)sizeof(intel_dp->lttpr_common_caps),
+ intel_dp->lttpr_common_caps);
+}
+
static u8 dp_voltage_max(u8 preemph)
{
switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
@@ -474,6 +492,28 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp)
schedule_work(&intel_connector->modeset_retry_work);
}
+static bool
+intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
+{
+ u8 val = enable ? DP_PHY_REPEATER_MODE_TRANSPARENT :
+ DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
+
+ return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
+}
+
+static void intel_dp_init_lttpr_mode(struct intel_dp *intel_dp)
+{
+ if (intel_dp_is_edp(intel_dp))
+ return;
+
+ /*
+ * TODO: the following re-reading of LTTPR caps can be removed
+ * after a proper connector HW readout is added.
+ */
+ intel_dp_read_lttpr_caps(intel_dp);
+ intel_dp_set_lttpr_transparent_mode(intel_dp, true);
+}
+
/**
* intel_dp_start_link_train - start link training
* @intel_dp: DP struct
@@ -485,6 +525,8 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp)
*/
void intel_dp_start_link_train(struct intel_dp *intel_dp)
{
+ intel_dp_init_lttpr_mode(intel_dp);
+
if (!intel_dp_link_train(intel_dp))
intel_dp_schedule_fallback_link_training(intel_dp);
}
@@ -12,6 +12,7 @@ struct intel_dp;
bool intel_dp_get_link_status(struct intel_dp *intel_dp,
u8 link_status[DP_LINK_STATUS_SIZE]);
+void intel_dp_read_lttpr_caps(struct intel_dp *intel_dp);
void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
const u8 link_status[DP_LINK_STATUS_SIZE]);
By default LTTPRs should be in transparent link training mode, nevertheless in this patch we switch to this default mode explicitly. The DP Standard recommends this, supposedly because an LTTPR may be left in the non-transparent mode (by BIOS, previous kernel, or after reset due to a firmware bug). I haven't seen this happening, but let's follow the DP Standard. Signed-off-by: Imre Deak <imre.deak@intel.com> --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 3 ++ .../drm/i915/display/intel_dp_link_training.c | 42 +++++++++++++++++++ .../drm/i915/display/intel_dp_link_training.h | 1 + 4 files changed, 47 insertions(+)