drm/nouveau/disp/sor/gf119-: add method to control mst enable
authorBen Skeggs <bskeggs@redhat.com>
Fri, 4 Nov 2016 07:20:35 +0000 (17:20 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 7 Nov 2016 04:04:42 +0000 (14:04 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvif/cl5070.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c

index d15c296b5f3352f0cdfaf1165e36a13273b1801a..ed999fc38833014cc27740b4d3329acd47c1d748 100644 (file)
@@ -34,6 +34,7 @@ struct nv50_disp_mthd_v1 {
 #define NV50_DISP_MTHD_V1_SOR_HDMI_PWR                                     0x22
 #define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT                                  0x23
 #define NV50_DISP_MTHD_V1_SOR_DP_PWR                                       0x24
+#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK                                  0x25
 #define NV50_DISP_MTHD_V1_PIOR_PWR                                         0x30
        __u8  method;
        __u16 hasht;
@@ -90,6 +91,12 @@ struct nv50_disp_sor_dp_pwr_v0 {
        __u8  pad02[6];
 };
 
+struct nv50_disp_sor_dp_mst_link_v0 {
+       __u8  version;
+       __u8  state;
+       __u8  pad02[6];
+};
+
 struct nv50_disp_pior_pwr_v0 {
        __u8  version;
        __u8  state;
index 0face69d63026464e1c40936b0a125840ffad1d7..fd9424101a650d510afe6511bcee4aec560771fa 100644 (file)
@@ -203,17 +203,19 @@ gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head)
        /* see note in nv50_disp_intr_unk20_0() */
        if (outp && outp->info.type == DCB_OUTPUT_DP) {
                struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
-               struct nvbios_init init = {
-                       .subdev = subdev,
-                       .bios = subdev->device->bios,
-                       .outp = &outp->info,
-                       .crtc = head,
-                       .offset = outpdp->info.script[4],
-                       .execute = 1,
-               };
+               if (!outpdp->lt.mst) {
+                       struct nvbios_init init = {
+                               .subdev = subdev,
+                               .bios = subdev->device->bios,
+                               .outp = &outp->info,
+                               .crtc = head,
+                               .offset = outpdp->info.script[4],
+                               .execute = 1,
+                       };
 
-               nvbios_exec(&init);
-               atomic_set(&outpdp->lt.done, 0);
+                       nvbios_exec(&init);
+                       atomic_set(&outpdp->lt.done, 0);
+               }
        }
 }
 
index 7b63d9737951bc1ae8f23b6c827e6957da8161a0..ef9ee0b771f3a2ab66c1d418786a9646bf3b0415 100644 (file)
@@ -32,6 +32,7 @@ struct nvkm_output_dp {
        struct mutex mutex;
        struct {
                atomic_t done;
+               bool mst;
        } lt;
 };
 
index e9548e4fbf21f7c5ab1b7ce764b6f34768271553..1a2506767755c4a37ef6458c3e60c7caccb900ed 100644 (file)
@@ -180,6 +180,26 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
                        return ret;
        }
                break;
+       case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: {
+               struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
+               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);
+                       if (outpdp->lt.mst != !!args->v0.state) {
+                               outpdp->lt.mst = !!args->v0.state;
+                               atomic_set(&outpdp->lt.done, 0);
+                               nvkm_output_dp_train(&outpdp->base, 0);
+                       }
+                       return 0;
+               } else
+                       return ret;
+       }
+               break;
        case NV50_DISP_MTHD_V1_PIOR_PWR:
                if (!func->pior.power)
                        return -ENODEV;
index 49bd5da194e1b368b0d069825e6fb03b03166684..520bf693df67f6aabc65c29bcd082c5298b7a01d 100644 (file)
@@ -56,11 +56,13 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 
        clksor |= bw << 18;
        dpctrl |= ((1 << nr) - 1) << 16;
+       if (outp->lt.mst)
+               dpctrl |= 0x40000000;
        if (ef)
                dpctrl |= 0x00004000;
 
        nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
-       nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl);
+       nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl);
        return 0;
 }