From 4423c743ef961153d274f3ec0704672ba979419c Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs@redhat.com>
Date: Fri, 19 May 2017 23:59:35 +1000
Subject: [PATCH] drm/nouveau/disp/dp: no need for lt_state except during manual link training
Git-commit: 4423c743ef961153d274f3ec0704672ba979419c
Patch-mainline: v4.13-rc1
References: bsc#1095094
This struct doesn't hold link configuration data anymore, so we can
limit its use to internal DP training (anx9805 handles training for
external DP).
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Acked-by: Takashi Iwai <tiwai@suse.de>
---
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 55 +++++++++++---------------
1 file changed, 24 insertions(+), 31 deletions(-)
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -196,9 +196,8 @@ nvkm_dp_train_cr(struct lt_state *lt)
}
static int
-nvkm_dp_train_links(struct lt_state *lt)
+nvkm_dp_train_links(struct nvkm_dp *dp)
{
- struct nvkm_dp *dp = lt->dp;
struct nvkm_ior *ior = dp->outp.ior;
struct nvkm_disp *disp = dp->outp.disp;
struct nvkm_subdev *subdev = &disp->engine.subdev;
@@ -211,6 +210,9 @@ nvkm_dp_train_links(struct lt_state *lt)
.crtc = -1,
.execute = 1,
};
+ struct lt_state lt = {
+ .dp = dp,
+ };
u32 lnkcmp;
u8 sink[2];
int ret;
@@ -220,11 +222,11 @@ nvkm_dp_train_links(struct lt_state *lt)
/* Intersect misc. capabilities of the OR and sink. */
if (disp->engine.subdev.device->chipset < 0xd0)
- dp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
- lt->pc2 = dp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED;
+ dp->dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED;
+ lt.pc2 = dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED;
/* Set desired link configuration on the source. */
- if ((lnkcmp = lt->dp->info.lnkcmp)) {
+ if ((lnkcmp = lt.dp->info.lnkcmp)) {
if (dp->version < 0x30) {
while ((ior->dp.bw * 2700) < nvbios_rd16(bios, lnkcmp))
lnkcmp += 4;
@@ -253,13 +255,22 @@ nvkm_dp_train_links(struct lt_state *lt)
if (ior->dp.ef)
sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN;
- return nvkm_wraux(dp->aux, DPCD_LC00_LINK_BW_SET, sink, 2);
+ ret = nvkm_wraux(dp->aux, DPCD_LC00_LINK_BW_SET, sink, 2);
+ if (ret)
+ return ret;
+
+ /* Attempt to train the link in this configuration. */
+ memset(lt.stat, 0x00, sizeof(lt.stat));
+ ret = nvkm_dp_train_cr(<);
+ if (ret == 0)
+ ret = nvkm_dp_train_eq(<);
+ nvkm_dp_train_pattern(<, 0);
+ return ret;
}
static void
-nvkm_dp_train_fini(struct lt_state *lt)
+nvkm_dp_train_fini(struct nvkm_dp *dp)
{
- struct nvkm_dp *dp = lt->dp;
struct nvkm_subdev *subdev = &dp->outp.disp->engine.subdev;
struct nvbios_init init = {
.subdev = subdev,
@@ -275,9 +286,8 @@ nvkm_dp_train_fini(struct lt_state *lt)
}
static void
-nvkm_dp_train_init(struct lt_state *lt)
+nvkm_dp_train_init(struct nvkm_dp *dp)
{
- struct nvkm_dp *dp = lt->dp;
struct nvkm_subdev *subdev = &dp->outp.disp->engine.subdev;
struct nvbios_init init = {
.subdev = subdev,
@@ -326,9 +336,6 @@ nvkm_dp_train(struct nvkm_dp *dp)
const u8 outp_nr = dp->outp.info.dpconf.link_nr;
const u8 outp_bw = dp->outp.info.dpconf.link_bw;
const struct dp_rates *cfg;
- struct lt_state lt = {
- .dp = dp,
- };
u8 pwr;
int ret;
@@ -345,8 +352,8 @@ nvkm_dp_train(struct nvkm_dp *dp)
}
/* Link training. */
- nvkm_dp_train_init(<);
- for (ret = -EINVAL, cfg = nvkm_dp_rates; cfg->rate; cfg++) {
+ nvkm_dp_train_init(dp);
+ for (ret = -EINVAL, cfg = nvkm_dp_rates; ret < 0 && cfg->rate; cfg++) {
/* Skip configurations not supported by both OR and sink. */
if (cfg[1].rate &&
(cfg->nr > outp_nr || cfg->bw > outp_bw ||
@@ -358,23 +365,9 @@ nvkm_dp_train(struct nvkm_dp *dp)
ior->dp.nr = cfg->nr;
/* Program selected link configuration. */
- ret = nvkm_dp_train_links(<);
- if (ret == 0) {
- /* Attempt to train the link in this configuration. */
- memset(lt.stat, 0x00, sizeof(lt.stat));
- if (!nvkm_dp_train_cr(<) &&
- !nvkm_dp_train_eq(<))
- break;
- } else
- if (ret) {
- /* nvkm_dp_train_links() handled training, or
- * we failed to communicate with the sink.
- */
- break;
- }
+ ret = nvkm_dp_train_links(dp);
}
- nvkm_dp_train_pattern(<, 0);
- nvkm_dp_train_fini(<);
+ nvkm_dp_train_fini(dp);
if (ret < 0)
OUTP_ERR(&dp->outp, "training failed");