from Todd Previte
Enable 5.4Ghz (HBR2) link rate for Displayport 1.2-capable devices
06ea66b6bb445043dc25a9626254d5c130093199 in mainline Linux

refactored to only support the GPU's both capable of HBR2 and 
currently supported by inteldrm: Broadwell and non-ULT Haswell

ok?

Index: sys/dev/pci/drm/i915/intel_dp.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/intel_dp.c,v
retrieving revision 1.26
diff -u -p -r1.26 intel_dp.c
--- sys/dev/pci/drm/i915/intel_dp.c     23 Sep 2015 23:12:12 -0000      1.26
+++ sys/dev/pci/drm/i915/intel_dp.c     1 Dec 2015 00:39:13 -0000
@@ -90,6 +90,17 @@ static struct intel_dp *intel_attached_d
 
 static void intel_dp_link_down(struct intel_dp *intel_dp);
 
+static bool intel_dp_hbr2_capable(struct intel_dp *intel_dp)
+{
+       struct drm_device *dev = intel_dp->attached_connector->base.dev;
+
+       if ((IS_BROADWELL(dev) || (IS_HASWELL(dev) && !IS_HSW_ULT(dev))) &&
+           intel_dp->dpcd[DP_DPCD_REV] >= 0x12)
+               return true;
+       else
+               return false;
+}
+
 static int
 intel_dp_max_link_bw(struct intel_dp *intel_dp)
 {
@@ -100,7 +111,8 @@ intel_dp_max_link_bw(struct intel_dp *in
        case DP_LINK_BW_2_7:
                break;
        case DP_LINK_BW_5_4: /* 1.2 capable displays may advertise higher bw */
-               max_link_bw = DP_LINK_BW_2_7;
+               if (!intel_dp_hbr2_capable(intel_dp))
+                       max_link_bw = DP_LINK_BW_2_7;
                break;
        default:
                WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
@@ -847,9 +859,10 @@ intel_dp_compute_config(struct intel_enc
        struct intel_connector *intel_connector = intel_dp->attached_connector;
        int lane_count, clock;
        int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
-       int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 
0;
+       /* Conveniently, the link BW constants become indices with a shift...*/
+       int max_clock = intel_dp_max_link_bw(intel_dp) >> 3;
        int bpp, mode_rate;
-       static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+       static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 };
        int link_avail, link_clock;
 
        if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A)
@@ -2673,10 +2686,15 @@ intel_dp_complete_link_train(struct inte
        bool channel_eq = false;
        int tries, cr_tries;
        uint32_t DP = intel_dp->DP;
+       uint32_t training_pattern = DP_TRAINING_PATTERN_2;
+
+       /* Training Pattern 3 for HBR2 on 1.2 devices that support it*/
+       if (intel_dp->link_bw == DP_LINK_BW_5_4 || intel_dp->use_tps3)
+               training_pattern = DP_TRAINING_PATTERN_3;
 
        /* channel equalization */
        if (!intel_dp_set_link_train(intel_dp, &DP,
-                                    DP_TRAINING_PATTERN_2 |
+                                    training_pattern |
                                     DP_LINK_SCRAMBLING_DISABLE)) {
                DRM_ERROR("failed to start channel equalization\n");
                return;
@@ -2703,7 +2721,7 @@ intel_dp_complete_link_train(struct inte
                if (!drm_dp_clock_recovery_ok(link_status, 
intel_dp->lane_count)) {
                        intel_dp_start_link_train(intel_dp);
                        intel_dp_set_link_train(intel_dp, &DP,
-                                               DP_TRAINING_PATTERN_2 |
+                                               training_pattern |
                                                DP_LINK_SCRAMBLING_DISABLE);
                        cr_tries++;
                        continue;
@@ -2719,7 +2737,7 @@ intel_dp_complete_link_train(struct inte
                        intel_dp_link_down(intel_dp);
                        intel_dp_start_link_train(intel_dp);
                        intel_dp_set_link_train(intel_dp, &DP,
-                                               DP_TRAINING_PATTERN_2 |
+                                               training_pattern |
                                                DP_LINK_SCRAMBLING_DISABLE);
                        tries = 0;
                        cr_tries++;
@@ -2864,6 +2882,14 @@ intel_dp_get_dpcd(struct intel_dp *intel
                        DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
                }
        }
+
+       /* Training Pattern 3 support */
+       if (intel_dp_hbr2_capable(intel_dp) &&
+           intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) {
+               intel_dp->use_tps3 = true;
+               DRM_DEBUG_KMS("Displayport TPS3 supported\n");
+       } else
+               intel_dp->use_tps3 = false;
 
        if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
              DP_DWN_STRM_PORT_PRESENT))
Index: sys/dev/pci/drm/i915/intel_drv.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/intel_drv.h,v
retrieving revision 1.8
diff -u -p -r1.8 intel_drv.h
--- sys/dev/pci/drm/i915/intel_drv.h    23 Sep 2015 23:12:12 -0000      1.8
+++ sys/dev/pci/drm/i915/intel_drv.h    1 Dec 2015 00:39:13 -0000
@@ -497,6 +497,7 @@ struct intel_dp {
        struct delayed_work panel_vdd_work;
        bool want_panel_vdd;
        bool psr_setup_done;
+       bool use_tps3;
        struct intel_connector *attached_connector;
 };
 

Reply via email to