diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2022-06-01 20:46:33 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2022-11-09 08:22:02 +1000 |
commit | 8134437213316a58d1844b87e2042ebf1fd9962c (patch) | |
tree | 59edc70bc07bdce83fbba76abc25238b634b7596 | |
parent | a9f5d7721923f6016578167640b8dd5cb0c5a698 (diff) | |
download | linux-8134437213316a58d1844b87e2042ebf1fd9962c.tar.bz2 |
drm/nouveau/disp: move DP link config into acquire
Aside from fixing MST->SST switching (KMS never turned off MST link config),
this should preserve existing behaviour for the moment, but provide a path
for the KMS driver to have more explicit control of the DP link, which has
been requested by Lyude.
More research into modeset/supervisor interactions is needed before we can
have fully explicit control from the KMS driver.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/disp.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/if0012.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/outp.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvif/outp.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 29 |
9 files changed, 65 insertions, 60 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index c61617acaf87..ca58c6b65339 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1014,7 +1014,7 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st if (!mstm->links++) { /*XXX: MST audio. */ - nvif_outp_acquire_dp(&mstm->outp->outp, false); + nvif_outp_acquire_dp(&mstm->outp->outp, mstm->outp->dp.dpcd, 0, 0, false, true); } if (mstm->outp->outp.or.link & 1) @@ -1380,26 +1380,6 @@ nv50_mstm_remove(struct nv50_mstm *mstm) drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); } -static int -nv50_mstm_enable(struct nv50_mstm *mstm, int state) -{ - struct nouveau_encoder *outp = mstm->outp; - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_dp_mst_link_v0 mst; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_LINK, - .base.hasht = outp->dcb->hasht, - .base.hashm = outp->dcb->hashm, - .mst.state = state, - }; - struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev); - struct nvif_object *disp = &drm->display->disp.object; - - return nvif_mthd(disp, 0, &args, sizeof(args)); -} - int nv50_mstm_detect(struct nouveau_encoder *outp) { @@ -1420,15 +1400,9 @@ nv50_mstm_detect(struct nouveau_encoder *outp) return ret; /* And start enabling */ - ret = nv50_mstm_enable(mstm, true); - if (ret) - return ret; - ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, true); - if (ret) { - nv50_mstm_enable(mstm, false); + if (ret) return ret; - } mstm->is_mst = true; return 1; @@ -1660,7 +1634,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta nvif_outp_acquire_lvds(&nv_encoder->outp, lvds_dual, lvds_8bpc); break; case DCB_OUTPUT_DP: - nvif_outp_acquire_dp(&nv_encoder->outp, hda); + nvif_outp_acquire_dp(&nv_encoder->outp, nv_encoder->dp.dpcd, 0, 0, hda, false); depth = nv50_dp_bpc_to_depth(asyh->or.bpc); if (nv_encoder->outp.or.link & 1) @@ -1858,7 +1832,7 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st break; case DCB_OUTPUT_DP: ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC); - nvif_outp_acquire_dp(&nv_encoder->outp, false); + nvif_outp_acquire_dp(&nv_encoder->outp, nv_encoder->dp.dpcd, 0, 0, false, false); break; default: BUG(); diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index a71317733748..15e30fbdc215 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -28,7 +28,6 @@ struct nv50_disp_scanoutpos_v0 { struct nv50_disp_mthd_v1 { __u8 version; -#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25 #define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26 __u8 method; __u16 hasht; @@ -36,12 +35,6 @@ struct nv50_disp_mthd_v1 { __u8 pad06[2]; }; -struct nv50_disp_sor_dp_mst_link_v0 { - __u8 version; - __u8 state; - __u8 pad02[6]; -}; - struct nv50_disp_sor_dp_mst_vcpi_v0 { __u8 version; __u8 pad01[1]; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index 938d384f5b1f..c67f03d52d8c 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -55,8 +55,12 @@ union nvif_outp_acquire_args { __u8 pad02[6]; } lvds; struct { + __u8 link_nr; /* 0 = highest possible. */ + __u8 link_bw; /* 0 = highest possible, DP BW code otherwise. */ __u8 hda; - __u8 pad01[7]; + __u8 mst; + __u8 pad04[4]; + __u8 dpcd[16]; } dp; }; } v0; diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index c8879d3428c8..88fd2b970304 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -21,7 +21,8 @@ int nvif_outp_acquire_rgb_crt(struct nvif_outp *); int nvif_outp_acquire_tmds(struct nvif_outp *, int head, bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda); int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8); -int nvif_outp_acquire_dp(struct nvif_outp *, bool hda); +int nvif_outp_acquire_dp(struct nvif_outp *, u8 dpcd[16], + int link_nr, int link_bw, bool hda, bool mst); void nvif_outp_release(struct nvif_outp *); int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size); int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size); diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 3a7c2d573e69..1ae5b19a8025 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -84,16 +84,22 @@ nvif_outp_acquire(struct nvif_outp *outp, u8 proto, struct nvif_outp_acquire_v0 } int -nvif_outp_acquire_dp(struct nvif_outp *outp, bool hda) +nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[16], + int link_nr, int link_bw, bool hda, bool mst) { struct nvif_outp_acquire_v0 args; int ret; + args.dp.link_nr = link_nr; + args.dp.link_bw = link_bw; args.dp.hda = hda; + args.dp.mst = mst; + memcpy(args.dp.dpcd, dpcd, sizeof(args.dp.dpcd)); ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DP, &args); NVIF_ERRON(ret, &outp->object, - "[ACQUIRE proto:DP hda:%d] or:%d link:%d", args.dp.hda, args.or, args.link); + "[ACQUIRE proto:DP link_nr:%d link_bw:%02x hda:%d mst:%d] or:%d link:%d", + args.dp.link_nr, args.dp.link_bw, args.dp.hda, args.dp.mst, args.or, args.link); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index c1b3206f27e6..f1887b58f472 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -287,7 +287,7 @@ nvkm_dp_train_links(struct nvkm_outp *outp, int rate) u8 sink[2], data; int ret; - OUTP_DBG(outp, "training %d x %d MB/s", ior->dp.nr, ior->dp.bw * 27); + OUTP_DBG(outp, "training %dx%02x", ior->dp.nr, ior->dp.bw); /* Intersect misc. capabilities of the OR and sink. */ if (disp->engine.subdev.device->chipset < 0x110) @@ -455,6 +455,21 @@ nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps) /* Link training. */ OUTP_DBG(outp, "training"); nvkm_dp_train_init(outp); + + /* Validate and train at configuration requested (if any) on ACQUIRE. */ + if (outp->dp.lt.nr) { + for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) { + for (rate = 0; nr == outp->dp.lt.nr && rate < outp->dp.rates; rate++) { + if (outp->dp.rate[rate].rate / 27000 == outp->dp.lt.bw) { + ior->dp.bw = outp->dp.rate[rate].rate / 27000; + ior->dp.nr = nr; + ret = nvkm_dp_train_links(outp, rate); + } + } + } + } + + /* Otherwise, loop through all valid link configurations that support the data rate. */ for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) { for (rate = 0; ret < 0 && rate < outp->dp.rates; rate++) { if (outp->dp.rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) { @@ -465,6 +480,8 @@ nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps) } } } + + /* Finish up. */ nvkm_dp_train_fini(outp); if (ret < 0) OUTP_ERR(outp, "training failed"); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index eb9cd1146825..d7c989e1cd01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -54,6 +54,8 @@ struct nvkm_outp { struct mutex mutex; struct { atomic_t done; + u8 nr; + u8 bw; bool mst; } lt; } dp; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index a5bb15b62a0c..2f42940367a0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -91,21 +91,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } switch (mthd * !!outp) { - case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: { - union { - struct nv50_disp_sor_dp_mst_link_v0 v0; - } *args = data; - int ret = -ENOSYS; - nvif_ioctl(object, "disp sor dp mst link size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "disp sor dp mst link vers %d state %d\n", - args->v0.version, args->v0.state); - outp->dp.lt.mst = !!args->v0.state; - return 0; - } else - return ret; - } - break; case NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI: { union { struct nv50_disp_sor_dp_mst_vcpi_v0 v0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index 052b2d14f47a..61d41b326f43 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -101,6 +101,23 @@ nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc) } static int +nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[16], + u8 link_nr, u8 link_bw, bool hda, bool mst) +{ + int ret; + + ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, hda); + if (ret) + return ret; + + memcpy(outp->dp.dpcd, dpcd, sizeof(outp->dp.dpcd)); + outp->dp.lt.nr = link_nr; + outp->dp.lt.bw = link_bw; + outp->dp.lt.mst = mst; + return 0; +} + +static int nvkm_uoutp_mthd_acquire_tmds(struct nvkm_outp *outp, u8 head, u8 hdmi, u8 hdmi_max_ac_packet, u8 hdmi_rekey, u8 hdmi_scdc, u8 hdmi_hda) { @@ -152,6 +169,8 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) if (argc != sizeof(args->v0) || args->v0.version != 0) return -ENOSYS; + if (outp->ior) + return -EBUSY; switch (args->v0.proto) { case NVIF_OUTP_ACQUIRE_V0_RGB_CRT: @@ -165,12 +184,16 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) args->v0.tmds.hdmi_scdc, args->v0.tmds.hdmi_hda); break; - case NVIF_OUTP_ACQUIRE_V0_DP: - ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, args->v0.dp.hda); - break; case NVIF_OUTP_ACQUIRE_V0_LVDS: ret = nvkm_uoutp_mthd_acquire_lvds(outp, args->v0.lvds.dual, args->v0.lvds.bpc8); break; + case NVIF_OUTP_ACQUIRE_V0_DP: + ret = nvkm_uoutp_mthd_acquire_dp(outp, args->v0.dp.dpcd, + args->v0.dp.link_nr, + args->v0.dp.link_bw, + args->v0.dp.hda != 0, + args->v0.dp.mst != 0); + break; default: ret = -EINVAL; break; |