|
@@ -135,6 +135,12 @@ intel_dp_link_required(struct drm_device *dev,
|
|
|
return pixel_clock * 3;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+intel_dp_max_data_rate(int max_link_clock, int max_lanes)
|
|
|
+{
|
|
|
+ return (max_link_clock * max_lanes * 8) / 10;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
intel_dp_mode_valid(struct drm_connector *connector,
|
|
|
struct drm_display_mode *mode)
|
|
@@ -144,8 +150,11 @@ intel_dp_mode_valid(struct drm_connector *connector,
|
|
|
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
|
|
|
int max_lanes = intel_dp_max_lane_count(intel_encoder);
|
|
|
|
|
|
- if (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
|
|
|
- > max_link_clock * max_lanes)
|
|
|
+ /* only refuse the mode on non eDP since we have seen some wierd eDP panels
|
|
|
+ which are outside spec tolerances but somehow work by magic */
|
|
|
+ if (!IS_eDP(intel_encoder) &&
|
|
|
+ (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
|
|
|
+ > intel_dp_max_data_rate(max_link_clock, max_lanes)))
|
|
|
return MODE_CLOCK_HIGH;
|
|
|
|
|
|
if (mode->clock < 10000)
|
|
@@ -506,7 +515,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|
|
|
|
|
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
|
|
|
for (clock = 0; clock <= max_clock; clock++) {
|
|
|
- int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
|
|
|
+ int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
|
|
|
|
|
|
if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)
|
|
|
<= link_avail) {
|
|
@@ -521,6 +530,18 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (IS_eDP(intel_encoder)) {
|
|
|
+ /* okay we failed just pick the highest */
|
|
|
+ dp_priv->lane_count = max_lane_count;
|
|
|
+ dp_priv->link_bw = bws[max_clock];
|
|
|
+ adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
|
|
|
+ DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
|
|
|
+ "count %d clock %d\n",
|
|
|
+ dp_priv->link_bw, dp_priv->lane_count,
|
|
|
+ adjusted_mode->clock);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
return false;
|
|
|
}
|
|
|
|