drm/i915: Track whether the DP link is trained or not
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 17 Jan 2018 19:21:49 +0000 (21:21 +0200)
committerLyude Paul <lyude@redhat.com>
Tue, 6 Mar 2018 22:59:08 +0000 (17:59 -0500)
LSPCON likes to throw short HPDs during the enable seqeunce prior to the
link being trained. These obviously result in the channel CR/EQ check
failing and thus we schedule a pointless hotplug work to retrain the
link. Avoid that by ignoring the bad CR/EQ status until we've actually
initially trained the link.

I've not actually investigated to see what LSPCON is trying to signal
with the short pulse. But as long as it signals anything I think we're
supposed to check the link status anyway, so I don't really see other
good ways to solve this. I've not seen these short pulses being
generated by normal DP sinks.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180117192149.17760-5-ville.syrjala@linux.intel.com
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_link_training.c
drivers/gpu/drm/i915/intel_drv.h

index d3cbea2c136c477efad03d764feea1f4eeb944a9..ac8fc2a44ac69612a1230209981b7dad6f085c4f 100644 (file)
@@ -2508,6 +2508,8 @@ static void intel_disable_ddi_dp(struct intel_encoder *encoder,
 {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
+       intel_dp->link_trained = false;
+
        if (old_crtc_state->has_audio)
                intel_audio_codec_disable(encoder,
                                          old_crtc_state, old_conn_state);
index 153342cf5898184ca92e1bb08ac4ba6256e7d671..9a4a51e79fa12a8c75a773258d33db5214655ea6 100644 (file)
@@ -1913,6 +1913,7 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp,
                              int link_rate, uint8_t lane_count,
                              bool link_mst)
 {
+       intel_dp->link_trained = false;
        intel_dp->link_rate = link_rate;
        intel_dp->lane_count = lane_count;
        intel_dp->link_mst = link_mst;
@@ -2761,6 +2762,8 @@ static void intel_disable_dp(struct intel_encoder *encoder,
 {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
+       intel_dp->link_trained = false;
+
        if (old_crtc_state->has_audio)
                intel_audio_codec_disable(encoder,
                                          old_crtc_state, old_conn_state);
@@ -4277,10 +4280,11 @@ intel_dp_needs_link_retrain(struct intel_dp *intel_dp)
 {
        u8 link_status[DP_LINK_STATUS_SIZE];
 
-       if (!intel_dp_get_link_status(intel_dp, link_status)) {
-               DRM_ERROR("Failed to get link status\n");
+       if (!intel_dp->link_trained)
+               return false;
+
+       if (!intel_dp_get_link_status(intel_dp, link_status))
                return false;
-       }
 
        /*
         * Validate the cached values of intel_dp->link_rate and
index ae849952d4b983a146bd102dbc59a65780411392..f59b59bb0a211a897dd0623bb19f092ec4761bad 100644 (file)
@@ -307,6 +307,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 
 void intel_dp_stop_link_train(struct intel_dp *intel_dp)
 {
+       intel_dp->link_trained = true;
+
        intel_dp_set_link_train(intel_dp,
                                DP_TRAINING_PATTERN_DISABLE);
 }
index dc693b40a884c9f2c5764606cc2cc470626af7e4..37d5412af8f5e6066a8883a612c2a7052ab2703d 100644 (file)
@@ -1048,6 +1048,7 @@ struct intel_dp {
        uint8_t lane_count;
        uint8_t sink_count;
        bool link_mst;
+       bool link_trained;
        bool has_audio;
        bool detect_done;
        bool reset_link_params;