Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 217976
b: refs/heads/master
c: 33a34e4
h: refs/heads/master
v: v3
  • Loading branch information
Jesse Barnes authored and Chris Wilson committed Sep 8, 2010
1 parent 46fb57d commit 8b7f82c
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 57 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b2094bbad48a59f59b115832879121aa210841f0
refs/heads/master: 33a34e4e5969c5272cd6cb88f2e01c97218dd80b
121 changes: 65 additions & 56 deletions trunk/drivers/gpu/drm/i915/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,17 @@ struct intel_dp {
struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo;
bool is_pch_edp;
uint8_t train_set[4];
uint8_t link_status[DP_LINK_STATUS_SIZE];
};

static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_dp, base);
}

static void intel_dp_link_train(struct intel_dp *intel_dp);
static void intel_dp_start_link_train(struct intel_dp *intel_dp);
static void intel_dp_complete_link_train(struct intel_dp *intel_dp);
static void intel_dp_link_down(struct intel_dp *intel_dp);

void
Expand Down Expand Up @@ -901,16 +904,16 @@ static void intel_dp_commit(struct drm_encoder *encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t dp_reg = I915_READ(intel_dp->output_reg);

if (!(dp_reg & DP_PORT_EN)) {
intel_dp_link_train(intel_dp);
}
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
intel_dp_start_link_train(intel_dp);

if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_panel_on(dev);

intel_dp_complete_link_train(intel_dp);

if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_backlight_on(dev);
}
}

static void
Expand All @@ -932,9 +935,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
ironlake_edp_pll_off(encoder);
} else {
if (!(dp_reg & DP_PORT_EN)) {
intel_dp_start_link_train(intel_dp);
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_panel_on(dev);
intel_dp_link_train(intel_dp);
intel_dp_complete_link_train(intel_dp);
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_backlight_on(dev);
}
Expand All @@ -947,14 +951,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
* link status information
*/
static bool
intel_dp_get_link_status(struct intel_dp *intel_dp,
uint8_t link_status[DP_LINK_STATUS_SIZE])
intel_dp_get_link_status(struct intel_dp *intel_dp)
{
int ret;

ret = intel_dp_aux_native_read(intel_dp,
DP_LANE0_1_STATUS,
link_status, DP_LINK_STATUS_SIZE);
intel_dp->link_status, DP_LINK_STATUS_SIZE);
if (ret != DP_LINK_STATUS_SIZE)
return false;
return true;
Expand Down Expand Up @@ -1029,18 +1032,15 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
}

static void
intel_get_adjust_train(struct intel_dp *intel_dp,
uint8_t link_status[DP_LINK_STATUS_SIZE],
int lane_count,
uint8_t train_set[4])
intel_get_adjust_train(struct intel_dp *intel_dp)
{
uint8_t v = 0;
uint8_t p = 0;
int lane;

for (lane = 0; lane < lane_count; lane++) {
uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane);
uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane);
for (lane = 0; lane < intel_dp->lane_count; lane++) {
uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane);
uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);

if (this_v > v)
v = this_v;
Expand All @@ -1055,7 +1055,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp,
p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;

for (lane = 0; lane < 4; lane++)
train_set[lane] = v | p;
intel_dp->train_set[lane] = v | p;
}

static uint32_t
Expand Down Expand Up @@ -1146,18 +1146,18 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count
DP_LANE_CHANNEL_EQ_DONE|\
DP_LANE_SYMBOL_LOCKED)
static bool
intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
intel_channel_eq_ok(struct intel_dp *intel_dp)
{
uint8_t lane_align;
uint8_t lane_status;
int lane;

lane_align = intel_dp_link_status(link_status,
lane_align = intel_dp_link_status(intel_dp->link_status,
DP_LANE_ALIGN_STATUS_UPDATED);
if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
return false;
for (lane = 0; lane < lane_count; lane++) {
lane_status = intel_get_lane_status(link_status, lane);
for (lane = 0; lane < intel_dp->lane_count; lane++) {
lane_status = intel_get_lane_status(intel_dp->link_status, lane);
if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
return false;
}
Expand All @@ -1168,7 +1168,6 @@ static bool
intel_dp_set_link_train(struct intel_dp *intel_dp,
uint32_t dp_reg_value,
uint8_t dp_train_pat,
uint8_t train_set[4],
bool first)
{
struct drm_device *dev = intel_dp->base.enc.dev;
Expand All @@ -1186,24 +1185,21 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
dp_train_pat);

ret = intel_dp_aux_native_write(intel_dp,
DP_TRAINING_LANE0_SET, train_set, 4);
DP_TRAINING_LANE0_SET, intel_dp->train_set, 4);
if (ret != 4)
return false;

return true;
}

/* Enable corresponding port and start training pattern 1 */
static void
intel_dp_link_train(struct intel_dp *intel_dp)
intel_dp_start_link_train(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.enc.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
uint8_t train_set[4];
uint8_t link_status[DP_LINK_STATUS_SIZE];
int i;
uint8_t voltage;
bool clock_recovery = false;
bool channel_eq = false;
bool first = true;
int tries;
u32 reg;
Expand All @@ -1219,18 +1215,18 @@ intel_dp_link_train(struct intel_dp *intel_dp)
DP &= ~DP_LINK_TRAIN_MASK_CPT;
else
DP &= ~DP_LINK_TRAIN_MASK;
memset(train_set, 0, 4);
memset(intel_dp->train_set, 0, 4);
voltage = 0xff;
tries = 0;
clock_recovery = false;
for (;;) {
/* Use train_set[0] to set the voltage and pre emphasis values */
/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
uint32_t signal_levels;
if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
} else {
signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
}

Expand All @@ -1240,52 +1236,65 @@ intel_dp_link_train(struct intel_dp *intel_dp)
reg = DP | DP_LINK_TRAIN_PAT_1;

if (!intel_dp_set_link_train(intel_dp, reg,
DP_TRAINING_PATTERN_1, train_set, first))
DP_TRAINING_PATTERN_1, first))
break;
first = false;
/* Set training pattern 1 */

udelay(100);
if (!intel_dp_get_link_status(intel_dp, link_status))
if (!intel_dp_get_link_status(intel_dp))
break;

if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
clock_recovery = true;
break;
}

/* Check to see if we've tried the max voltage */
for (i = 0; i < intel_dp->lane_count; i++)
if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
break;
if (i == intel_dp->lane_count)
break;

/* Check to see if we've tried the same voltage 5 times */
if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
++tries;
if (tries == 5)
break;
} else
tries = 0;
voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;

/* Compute new train_set as requested by target */
intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
/* Compute new intel_dp->train_set as requested by target */
intel_get_adjust_train(intel_dp);
}

intel_dp->DP = DP;
}

static void
intel_dp_complete_link_train(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.enc.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
bool channel_eq = false;
int tries;
u32 reg;
uint32_t DP = intel_dp->DP;

/* channel equalization */
tries = 0;
channel_eq = false;
for (;;) {
/* Use train_set[0] to set the voltage and pre emphasis values */
/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
uint32_t signal_levels;

if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
} else {
signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
}

Expand All @@ -1296,15 +1305,15 @@ intel_dp_link_train(struct intel_dp *intel_dp)

/* channel eq pattern */
if (!intel_dp_set_link_train(intel_dp, reg,
DP_TRAINING_PATTERN_2, train_set,
DP_TRAINING_PATTERN_2,
false))
break;

udelay(400);
if (!intel_dp_get_link_status(intel_dp, link_status))
if (!intel_dp_get_link_status(intel_dp))
break;

if (intel_channel_eq_ok(link_status, intel_dp->lane_count)) {
if (intel_channel_eq_ok(intel_dp)) {
channel_eq = true;
break;
}
Expand All @@ -1313,8 +1322,8 @@ intel_dp_link_train(struct intel_dp *intel_dp)
if (tries > 5)
break;

/* Compute new train_set as requested by target */
intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
/* Compute new intel_dp->train_set as requested by target */
intel_get_adjust_train(intel_dp);
++tries;
}

Expand Down Expand Up @@ -1375,18 +1384,18 @@ intel_dp_link_down(struct intel_dp *intel_dp)
static void
intel_dp_check_link_status(struct intel_dp *intel_dp)
{
uint8_t link_status[DP_LINK_STATUS_SIZE];

if (!intel_dp->base.enc.crtc)
return;

if (!intel_dp_get_link_status(intel_dp, link_status)) {
if (!intel_dp_get_link_status(intel_dp)) {
intel_dp_link_down(intel_dp);
return;
}

if (!intel_channel_eq_ok(link_status, intel_dp->lane_count))
intel_dp_link_train(intel_dp);
if (!intel_channel_eq_ok(intel_dp)) {
intel_dp_start_link_train(intel_dp);
intel_dp_complete_link_train(intel_dp);
}
}

static enum drm_connector_status
Expand Down

0 comments on commit 8b7f82c

Please sign in to comment.