Commit 2edd5327 authored by Manasi Navare's avatar Manasi Navare Committed by Paulo Zanoni

drm/i915/dp: Add support for HBR3 and TPS4 during link training

DP spec 1.4 supports training pattern set 4 (TPS4) for HBR3 link
rate. This will be used in link training's channel equalization
phase if supported by both source and sink.
This patch adds the helpers to check if HBR3 is supported and uses
TPS4 in training pattern selection during link training.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Reviewed-by: default avatarJames Ausmus <james.ausmus@intel.com>
Signed-off-by: default avatarManasi Navare <manasi.d.navare@intel.com>
Signed-off-by: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180611222655.5696-2-paulo.r.zanoni@intel.com
parent 46b527d1
...@@ -8703,6 +8703,7 @@ enum skl_power_gate { ...@@ -8703,6 +8703,7 @@ enum skl_power_gate {
#define DP_TP_CTL_LINK_TRAIN_PAT1 (0<<8) #define DP_TP_CTL_LINK_TRAIN_PAT1 (0<<8)
#define DP_TP_CTL_LINK_TRAIN_PAT2 (1<<8) #define DP_TP_CTL_LINK_TRAIN_PAT2 (1<<8)
#define DP_TP_CTL_LINK_TRAIN_PAT3 (4<<8) #define DP_TP_CTL_LINK_TRAIN_PAT3 (4<<8)
#define DP_TP_CTL_LINK_TRAIN_PAT4 (5<<8)
#define DP_TP_CTL_LINK_TRAIN_IDLE (2<<8) #define DP_TP_CTL_LINK_TRAIN_IDLE (2<<8)
#define DP_TP_CTL_LINK_TRAIN_NORMAL (3<<8) #define DP_TP_CTL_LINK_TRAIN_NORMAL (3<<8)
#define DP_TP_CTL_SCRAMBLE_DISABLE (1<<7) #define DP_TP_CTL_SCRAMBLE_DISABLE (1<<7)
......
...@@ -1565,6 +1565,13 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) ...@@ -1565,6 +1565,13 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)
return max_rate >= 540000; return max_rate >= 540000;
} }
bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp)
{
int max_rate = intel_dp->source_rates[intel_dp->num_source_rates - 1];
return max_rate >= 810000;
}
static void static void
intel_dp_set_clock(struct intel_encoder *encoder, intel_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config) struct intel_crtc_state *pipe_config)
...@@ -2889,10 +2896,11 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -2889,10 +2896,11 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
enum port port = intel_dig_port->base.port; enum port port = intel_dig_port->base.port;
uint8_t train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd);
if (dp_train_pat & DP_TRAINING_PATTERN_MASK) if (dp_train_pat & train_pat_mask)
DRM_DEBUG_KMS("Using DP training pattern TPS%d\n", DRM_DEBUG_KMS("Using DP training pattern TPS%d\n",
dp_train_pat & DP_TRAINING_PATTERN_MASK); dp_train_pat & train_pat_mask);
if (HAS_DDI(dev_priv)) { if (HAS_DDI(dev_priv)) {
uint32_t temp = I915_READ(DP_TP_CTL(port)); uint32_t temp = I915_READ(DP_TP_CTL(port));
...@@ -2903,7 +2911,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -2903,7 +2911,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { switch (dp_train_pat & train_pat_mask) {
case DP_TRAINING_PATTERN_DISABLE: case DP_TRAINING_PATTERN_DISABLE:
temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
...@@ -2917,6 +2925,9 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -2917,6 +2925,9 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
case DP_TRAINING_PATTERN_3: case DP_TRAINING_PATTERN_3:
temp |= DP_TP_CTL_LINK_TRAIN_PAT3; temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
break; break;
case DP_TRAINING_PATTERN_4:
temp |= DP_TP_CTL_LINK_TRAIN_PAT4;
break;
} }
I915_WRITE(DP_TP_CTL(port), temp); I915_WRITE(DP_TP_CTL(port), temp);
......
...@@ -219,14 +219,30 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) ...@@ -219,14 +219,30 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
} }
/* /*
* Pick training pattern for channel equalization. Training Pattern 3 for HBR2 * Pick training pattern for channel equalization. Training pattern 4 for HBR3
* or for 1.4 devices that support it, training Pattern 3 for HBR2
* or 1.2 devices that support it, Training Pattern 2 otherwise. * or 1.2 devices that support it, Training Pattern 2 otherwise.
*/ */
static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
{ {
u32 training_pattern = DP_TRAINING_PATTERN_2; bool source_tps3, sink_tps3, source_tps4, sink_tps4;
bool source_tps3, sink_tps3;
/*
* Intel platforms that support HBR3 also support TPS4. It is mandatory
* for all downstream devices that support HBR3. There are no known eDP
* panels that support TPS4 as of Feb 2018 as per VESA eDP_v1.4b_E1
* specification.
*/
source_tps4 = intel_dp_source_supports_hbr3(intel_dp);
sink_tps4 = drm_dp_tps4_supported(intel_dp->dpcd);
if (source_tps4 && sink_tps4) {
return DP_TRAINING_PATTERN_4;
} else if (intel_dp->link_rate == 810000) {
if (!source_tps4)
DRM_DEBUG_KMS("8.1 Gbps link rate without source HBR3/TPS4 support\n");
if (!sink_tps4)
DRM_DEBUG_KMS("8.1 Gbps link rate without sink TPS4 support\n");
}
/* /*
* Intel platforms that support HBR2 also support TPS3. TPS3 support is * Intel platforms that support HBR2 also support TPS3. TPS3 support is
* also mandatory for downstream devices that support HBR2. However, not * also mandatory for downstream devices that support HBR2. However, not
...@@ -234,17 +250,16 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) ...@@ -234,17 +250,16 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
*/ */
source_tps3 = intel_dp_source_supports_hbr2(intel_dp); source_tps3 = intel_dp_source_supports_hbr2(intel_dp);
sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd);
if (source_tps3 && sink_tps3) { if (source_tps3 && sink_tps3) {
training_pattern = DP_TRAINING_PATTERN_3; return DP_TRAINING_PATTERN_3;
} else if (intel_dp->link_rate == 540000) { } else if (intel_dp->link_rate >= 540000) {
if (!source_tps3) if (!source_tps3)
DRM_DEBUG_KMS("5.4 Gbps link rate without source HBR2/TPS3 support\n"); DRM_DEBUG_KMS(">=5.4/6.48 Gbps link rate without source HBR2/TPS3 support\n");
if (!sink_tps3) if (!sink_tps3)
DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n"); DRM_DEBUG_KMS(">=5.4/6.48 Gbps link rate without sink TPS3 support\n");
} }
return training_pattern; return DP_TRAINING_PATTERN_2;
} }
static bool static bool
...@@ -256,11 +271,13 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) ...@@ -256,11 +271,13 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
bool channel_eq = false; bool channel_eq = false;
training_pattern = intel_dp_training_pattern(intel_dp); training_pattern = intel_dp_training_pattern(intel_dp);
/* Scrambling is disabled for TPS2/3 and enabled for TPS4 */
if (training_pattern != DP_TRAINING_PATTERN_4)
training_pattern |= DP_LINK_SCRAMBLING_DISABLE;
/* channel equalization */ /* channel equalization */
if (!intel_dp_set_link_train(intel_dp, if (!intel_dp_set_link_train(intel_dp,
training_pattern | training_pattern)) {
DP_LINK_SCRAMBLING_DISABLE)) {
DRM_ERROR("failed to start channel equalization\n"); DRM_ERROR("failed to start channel equalization\n");
return false; return false;
} }
......
...@@ -1715,6 +1715,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing); ...@@ -1715,6 +1715,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing);
void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
uint8_t *link_bw, uint8_t *rate_select); uint8_t *link_bw, uint8_t *rate_select);
bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp);
bool bool
intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]); intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment