]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drm/nouveau/disp/dp: use cached link configuration when checking link status
authorBen Skeggs <bskeggs@redhat.com>
Fri, 19 May 2017 13:59:35 +0000 (23:59 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 16 Jun 2017 04:04:51 +0000 (14:04 +1000)
Saves some trips across the aux channel.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c

index 2b3aca044975bb6226d2c693b23ba3e39ff891b7..4941643dd8fa381c7f5647da51ef3dd04ed824a8 100644 (file)
@@ -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);