Message ID | 20180524234241.3665-3-paulo.r.zanoni@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, May 24, 2018 at 04:42:38PM -0700, Paulo Zanoni wrote: > From: Manasi Navare <manasi.d.navare@intel.com> > > 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: James Ausmus <james.ausmus@intel.com> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> > Cc: Jani Nikula <jani.nikula@linux.intel.com> > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com> Reviewed-by: James Ausmus <james.ausmus@intel.com> > --- > drivers/gpu/drm/i915/i915_reg.h | 1 + > drivers/gpu/drm/i915/intel_dp.c | 17 +++++++++--- > drivers/gpu/drm/i915/intel_dp_link_training.c | 39 +++++++++++++++++++-------- > drivers/gpu/drm/i915/intel_drv.h | 1 + > 4 files changed, 44 insertions(+), 14 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index e48b717769b2..ae7070c0806d 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -8791,6 +8791,7 @@ enum skl_power_gate { > #define DP_TP_CTL_LINK_TRAIN_PAT1 (0<<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_PAT4 (5<<8) > #define DP_TP_CTL_LINK_TRAIN_IDLE (2<<8) > #define DP_TP_CTL_LINK_TRAIN_NORMAL (3<<8) > #define DP_TP_CTL_SCRAMBLE_DISABLE (1<<7) > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index 3ee8e74cf2b8..bcc3f330b301 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -1721,6 +1721,13 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) > 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 > intel_dp_set_clock(struct intel_encoder *encoder, > struct intel_crtc_state *pipe_config) > @@ -3046,10 +3053,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 intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); > 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", > - dp_train_pat & DP_TRAINING_PATTERN_MASK); > + dp_train_pat & train_pat_mask); > > if (HAS_DDI(dev_priv)) { > uint32_t temp = I915_READ(DP_TP_CTL(port)); > @@ -3060,7 +3068,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, > temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; > > 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: > temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; > > @@ -3074,6 +3082,9 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, > case DP_TRAINING_PATTERN_3: > temp |= DP_TP_CTL_LINK_TRAIN_PAT3; > break; > + case DP_TRAINING_PATTERN_4: > + temp |= DP_TP_CTL_LINK_TRAIN_PAT4; > + break; > } > I915_WRITE(DP_TP_CTL(port), temp); > > diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c > index 3fcaa98b9055..4da6e33c7fa1 100644 > --- a/drivers/gpu/drm/i915/intel_dp_link_training.c > +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c > @@ -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. > */ > static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) > { > - u32 training_pattern = DP_TRAINING_PATTERN_2; > - bool source_tps3, sink_tps3; > + bool source_tps3, sink_tps3, source_tps4, sink_tps4; > > + /* > + * 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 > * 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) > */ > source_tps3 = intel_dp_source_supports_hbr2(intel_dp); > sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); > - > if (source_tps3 && sink_tps3) { > - training_pattern = DP_TRAINING_PATTERN_3; > - } else if (intel_dp->link_rate == 540000) { > + return DP_TRAINING_PATTERN_3; > + } else if (intel_dp->link_rate >= 540000) { > 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) > - 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 > @@ -256,11 +271,13 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) > bool channel_eq = false; > > 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 */ > if (!intel_dp_set_link_train(intel_dp, > - training_pattern | > - DP_LINK_SCRAMBLING_DISABLE)) { > + training_pattern)) { > DRM_ERROR("failed to start channel equalization\n"); > return false; > } > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index e3c2419301b4..c97a7ab3a2b1 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -1718,6 +1718,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, > uint8_t *link_bw, uint8_t *rate_select); > bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); > +bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp); > bool > intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]); > > -- > 2.14.3 >
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e48b717769b2..ae7070c0806d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8791,6 +8791,7 @@ enum skl_power_gate { #define DP_TP_CTL_LINK_TRAIN_PAT1 (0<<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_PAT4 (5<<8) #define DP_TP_CTL_LINK_TRAIN_IDLE (2<<8) #define DP_TP_CTL_LINK_TRAIN_NORMAL (3<<8) #define DP_TP_CTL_SCRAMBLE_DISABLE (1<<7) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3ee8e74cf2b8..bcc3f330b301 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1721,6 +1721,13 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) 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 intel_dp_set_clock(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) @@ -3046,10 +3053,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 intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); 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", - dp_train_pat & DP_TRAINING_PATTERN_MASK); + dp_train_pat & train_pat_mask); if (HAS_DDI(dev_priv)) { uint32_t temp = I915_READ(DP_TP_CTL(port)); @@ -3060,7 +3068,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; 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: temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; @@ -3074,6 +3082,9 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, case DP_TRAINING_PATTERN_3: temp |= DP_TP_CTL_LINK_TRAIN_PAT3; break; + case DP_TRAINING_PATTERN_4: + temp |= DP_TP_CTL_LINK_TRAIN_PAT4; + break; } I915_WRITE(DP_TP_CTL(port), temp); diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index 3fcaa98b9055..4da6e33c7fa1 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -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. */ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) { - u32 training_pattern = DP_TRAINING_PATTERN_2; - bool source_tps3, sink_tps3; + bool source_tps3, sink_tps3, source_tps4, sink_tps4; + /* + * 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 * 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) */ source_tps3 = intel_dp_source_supports_hbr2(intel_dp); sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); - if (source_tps3 && sink_tps3) { - training_pattern = DP_TRAINING_PATTERN_3; - } else if (intel_dp->link_rate == 540000) { + return DP_TRAINING_PATTERN_3; + } else if (intel_dp->link_rate >= 540000) { 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) - 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 @@ -256,11 +271,13 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) bool channel_eq = false; 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 */ if (!intel_dp_set_link_train(intel_dp, - training_pattern | - DP_LINK_SCRAMBLING_DISABLE)) { + training_pattern)) { DRM_ERROR("failed to start channel equalization\n"); return false; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e3c2419301b4..c97a7ab3a2b1 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1718,6 +1718,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, uint8_t *link_bw, uint8_t *rate_select); bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); +bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp); bool intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]);