summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2017-05-19 23:59:35 +1000
committerBen Skeggs <bskeggs@redhat.com>2017-06-16 14:04:51 +1000
commitfafa8b5c9f7426cef6b9b52b8582a867edbc7a06 (patch)
treee0788b0e06150890bec15cd42c21874b193ea2c4 /drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
parent4423c743ef961153d274f3ec0704672ba979419c (diff)
drm/nouveau/disp/dp: use cached link configuration when checking link status
Saves some trips across the aux channel. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c39
1 files changed, 17 insertions, 22 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
index 2b3aca044975..4941643dd8fa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -326,7 +326,7 @@ static const struct dp_rates {
{}
};
-static void
+static int
nvkm_dp_train(struct nvkm_dp *dp)
{
struct nv50_disp *disp = nv50_disp(dp->outp.disp);
@@ -370,39 +370,34 @@ nvkm_dp_train(struct nvkm_dp *dp)
nvkm_dp_train_fini(dp);
if (ret < 0)
OUTP_ERR(&dp->outp, "training failed");
-
- OUTP_DBG(&dp->outp, "training done");
+ else
+ OUTP_DBG(&dp->outp, "training done");
atomic_set(&dp->lt.done, 1);
+ return ret;
}
int
-nvkm_output_dp_train(struct nvkm_outp *outp, u32 datarate)
+nvkm_output_dp_train(struct nvkm_outp *outp, u32 datakbps)
{
struct nvkm_dp *dp = nvkm_dp(outp);
+ struct nvkm_ior *ior = dp->outp.ior;
bool retrain = true;
- u8 link[2], stat[3];
- u32 linkrate;
+ u32 linkKBps;
+ u32 dataKBps;
+ u8 stat[3];
int ret, i;
mutex_lock(&dp->mutex);
- /* check that the link is trained at a high enough rate */
- ret = nvkm_rdaux(dp->aux, DPCD_LC00_LINK_BW_SET, link, 2);
- if (ret) {
- OUTP_DBG(&dp->outp,
- "failed to read link config, assuming no sink");
- goto done;
- }
-
- linkrate = link[0] * 27000 * (link[1] & DPCD_LC01_LANE_COUNT_SET);
- linkrate = (linkrate * 8) / 10; /* 8B/10B coding overhead */
- datarate = (datarate + 9) / 10; /* -> decakilobits */
- if (linkrate < datarate) {
- OUTP_DBG(&dp->outp, "link not trained at sufficient rate");
+ /* Check that link configuration meets current requirements. */
+ linkKBps = ior->dp.bw * 27000 * ior->dp.nr;
+ dataKBps = DIV_ROUND_UP(datakbps, 8);
+ if (linkKBps < dataKBps) {
+ OUTP_DBG(&dp->outp, "link requirements changed");
goto done;
}
- /* check that link is still trained */
+ /* Check that link is still trained. */
ret = nvkm_rdaux(dp->aux, DPCD_LS02, stat, 3);
if (ret) {
OUTP_DBG(&dp->outp,
@@ -411,7 +406,7 @@ nvkm_output_dp_train(struct nvkm_outp *outp, u32 datarate)
}
if (stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE) {
- for (i = 0; i < (link[1] & DPCD_LC01_LANE_COUNT_SET); i++) {
+ for (i = 0; i < ior->dp.nr; i++) {
u8 lane = (stat[i >> 1] >> ((i & 1) * 4)) & 0x0f;
if (!(lane & DPCD_LS02_LANE0_CR_DONE) ||
!(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) ||
@@ -435,7 +430,7 @@ done:
dp->dpcd[DPCD_RC02] =
dp->outp.info.dpconf.link_nr;
}
- nvkm_dp_train(dp);
+ ret = nvkm_dp_train(dp);
}
mutex_unlock(&dp->mutex);