static int rk_edp_link_train_ce(struct rk_edp_priv *edp) { struct rk3288_edp *regs = edp->regs; int channel_eq; u8 value; int tries; u8 status[DP_LINK_STATUS_SIZE]; int ret; value = DP_TRAINING_PATTERN_2; writel(value, ®s->dp_training_ptn_set); ret = rk_edp_dpcd_write(regs, DPCD_TRAINING_PATTERN_SET, &value, 1); if (ret) return ret; /* channel equalization loop */ channel_eq = 0; for (tries = 0; tries < 5; tries++) { rk_edp_set_link_training(edp, edp->train_set); udelay(400); if (rk_edp_dpcd_read_link_status(edp, status) < 0) { printf("displayport link status failed\n"); return -1; } channel_eq = rk_edp_channel_eq(status, edp->link_train.lane_count); if (!channel_eq) break; edp_get_adjust_train(status, edp->link_train.lane_count, edp->train_set); } if (channel_eq) { printf("channel eq failed, ret=%d\n", channel_eq); return channel_eq; } debug("channel eq at voltage %d pre-emphasis %d\n", edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT); return 0; }
static int rk_edp_link_train_ce(struct rk_edp *edp) { int channel_eq; u8 value, tries = 0; u8 status[DP_LINK_STATUS_SIZE]; value = DP_TRAINING_PATTERN_2; write32(&edp->regs->dp_training_ptn_set, value); rk_edp_dpcd_write(edp, DPCD_TRAINING_PATTERN_SET, &value, 1); /* channel equalization loop */ channel_eq = 0; for (tries = 0; tries < 5; tries++) { rk_edp_set_link_training(edp, edp->train_set); rk_edp_dpcd_write(edp, DPCD_TRAINING_LANE0_SET, edp->train_set, edp->link_train.lane_count); udelay(400); if (rk_edp_dpcd_read_link_status(edp, status) < 0) { printk(BIOS_ERR, "displayport link status failed\n"); return -1; } if (rk_edp_channel_eq_ok(status, edp->link_train.lane_count)) { channel_eq = 1; break; } edp_get_adjust_train(status, edp->link_train.lane_count, edp->train_set); } if (!channel_eq) { printk(BIOS_ERR, "channel eq failed\n"); return -1; } else { printk(BIOS_DEBUG, "channel eq at voltage %d pre-emphasis %d\n", edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT); return 0; } }
static int rk_edp_link_train_cr(struct rk_edp *edp) { int clock_recovery; u8 voltage, tries = 0; u8 status[DP_LINK_STATUS_SIZE]; int i; u8 value; value = DP_TRAINING_PATTERN_1; write32(&edp->regs->dp_training_ptn_set, value); rk_edp_dpcd_write(edp, DPCD_TRAINING_PATTERN_SET, &value, 1); memset(edp->train_set, 0, 4); /* clock recovery loop */ clock_recovery = 0; tries = 0; voltage = 0xff; while (1) { rk_edp_set_link_training(edp, edp->train_set); rk_edp_dpcd_write(edp, DPCD_TRAINING_LANE0_SET, edp->train_set, edp->link_train.lane_count); mdelay(1); if (rk_edp_dpcd_read_link_status(edp, status) < 0) { printk(BIOS_ERR, "displayport link status failed\n"); break; } if (rk_edp_clock_recovery_ok(status, edp->link_train.lane_count)) { clock_recovery = 1; break; } for (i = 0; i < edp->link_train.lane_count; i++) { if ((edp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; } if (i == edp->link_train.lane_count) { printk(BIOS_ERR, "clock recovery reached max voltage\n"); break; } if ((edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { ++tries; if (tries == MAX_CR_LOOP) { printk(BIOS_ERR, "clock recovery tried 5 times\n"); break; } } else tries = 0; voltage = edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Compute new train_set as requested by sink */ edp_get_adjust_train(status, edp->link_train.lane_count, edp->train_set); } if (!clock_recovery) { printk(BIOS_ERR, "clock recovery failed\n"); return -1; } else { printk(BIOS_DEBUG, "clock recovery at voltage %d pre-emphasis %d\n", edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT); return 0; } }
static int rk_edp_link_train_cr(struct rk_edp_priv *edp) { struct rk3288_edp *regs = edp->regs; int clock_recovery; uint voltage, tries = 0; u8 status[DP_LINK_STATUS_SIZE]; int i, ret; u8 value; value = DP_TRAINING_PATTERN_1; writel(value, ®s->dp_training_ptn_set); ret = rk_edp_dpcd_write(regs, DPCD_TRAINING_PATTERN_SET, &value, 1); if (ret) return ret; memset(edp->train_set, '\0', sizeof(edp->train_set)); /* clock recovery loop */ clock_recovery = 0; tries = 0; voltage = 0xff; while (1) { rk_edp_set_link_training(edp, edp->train_set); ret = rk_edp_dpcd_write(regs, DPCD_TRAINING_LANE0_SET, edp->train_set, edp->link_train.lane_count); if (ret) return ret; mdelay(1); ret = rk_edp_dpcd_read_link_status(edp, status); if (ret) { printf("displayport link status failed, ret=%d\n", ret); break; } clock_recovery = rk_edp_clock_recovery(status, edp->link_train.lane_count); if (!clock_recovery) break; for (i = 0; i < edp->link_train.lane_count; i++) { if ((edp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; } if (i == edp->link_train.lane_count) { printf("clock recovery reached max voltage\n"); break; } if ((edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { if (++tries == MAX_CR_LOOP) { printf("clock recovery tried 5 times\n"); break; } } else { tries = 0; } voltage = edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Compute new train_set as requested by sink */ edp_get_adjust_train(status, edp->link_train.lane_count, edp->train_set); } if (clock_recovery) { printf("clock recovery failed: %d\n", clock_recovery); return clock_recovery; } else { debug("clock recovery at voltage %d pre-emphasis %d\n", edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT); return 0; } }