summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-06-30 11:46:17 +1000
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-13 13:27:36 -0700
commitbce2d0a8ec0e4160fa84a054838d334e82fd6cc3 (patch)
tree5a0bcbdc6cebb34e6f76e2775369a127c435201e
parent4bab121beebb1ee0dfad5493529d0bba8886bf49 (diff)
i915: fix ironlake edp panel setup (v4)
commit fe27d53e5c597ee5ba5d72a29d517091f244e974 upstream. The eDP spec claims a 20% overhead for the 8:10 encoding scheme used on the wire. Take this into account when picking the lane/clock speed for the panel. v3: some panels are out of spec, try our best to deal with them, don't refuse modes on eDP panels, and try the largest allowed settings if all else fails on eDP. v4: fix stupid typo, forgot to git add before amending. Fixes several reports in bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=28070 Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Eric Anholt <eric@anholt.net> Cc: Manoj Iyer <manoj.iyer@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a9ec41ddd030..f3902d37796f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -138,6 +138,12 @@ intel_dp_link_required(struct drm_device *dev,
}
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)
{
@@ -145,8 +151,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)
@@ -498,7 +507,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) {
@@ -513,6 +522,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;
}