drm/nouveau/disp: keep track of high-speed state, program into clock
authorIlia Mirkin <imirkin@alum.mit.edu>
Tue, 4 Sep 2018 00:57:35 +0000 (20:57 -0400)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 10 Oct 2018 23:54:10 +0000 (09:54 +1000)
The register programmed by the clock method needs to contain a different
setting for the link speed as well as special divider settings.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c

index ad5f658c3f6d362a338213dd8d4998fed09244d3..9b16a08eb4d9f49c1d00b27fca9608e701dc2d5c 100644 (file)
@@ -31,4 +31,6 @@ gm200_hdmi_scdc(struct nvkm_ior *ior, int head, u8 scdc)
        const u32 ctrl = scdc & 0x3;
 
        nvkm_mask(device, 0x61c5bc + hoff, 0x00000003, ctrl);
+
+       ior->tmds.high_speed = !!(scdc & 0x2);
 }
index c5d34424f45f5890b346306113a83519518cd702..0f0c86c32ec3affd8472948a7232cc17647dd028 100644 (file)
@@ -41,6 +41,11 @@ struct nvkm_ior {
                u8 nr;
                u8 bw;
        } dp;
+
+       /* Armed TMDS state. */
+       struct {
+               bool high_speed;
+       } tmds;
 };
 
 struct nvkm_ior_func {
index e6e6dfbb1283d41f5937c48bc23c054c73f55066..456a5a143522ae19cb2cd1011a08da4811429fe3 100644 (file)
@@ -120,13 +120,16 @@ void
 gf119_sor_clock(struct nvkm_ior *sor)
 {
        struct nvkm_device *device = sor->disp->engine.subdev.device;
-       const int  div = sor->asy.link == 3;
        const u32 soff = nv50_ior_base(sor);
+       u32 div1 = sor->asy.link == 3;
+       u32 div2 = sor->asy.link == 3;
        if (sor->asy.proto == TMDS) {
-               /* NFI why, but this sets DP_LINK_BW_2_7 when using TMDS. */
-               nvkm_mask(device, 0x612300 + soff, 0x007c0000, 0x0a << 18);
+               const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a;
+               nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18);
+               if (sor->tmds.high_speed)
+                       div2 = 1;
        }
-       nvkm_mask(device, 0x612300 + soff, 0x00000707, (div << 8) | div);
+       nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1);
 }
 
 void