drm/nouveau/disp/gm200-: detect and potentially disable HDA support on some SORs
authorBen Skeggs <bskeggs@redhat.com>
Wed, 3 Jun 2020 02:51:03 +0000 (12:51 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 4 Jun 2020 04:23:21 +0000 (14:23 +1000)
Some HDA pin widgets may be disabled by BIOS, and unavailable from a
SOR.  Our SOR allocation policy uses this information to allocate an
appropriate SOR when HDA is supported by a display.

Thank you to NVIDIA for providing the information to determine this.

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

index cf2075db742a21a60db77145ea27e451f34a8343..4dd7f382968ed1bc4cfac8c03a4201e1b919b3d7 100644 (file)
@@ -89,7 +89,7 @@ gm200_sor_route_get(struct nvkm_outp *outp, int *link)
 }
 
 static const struct nvkm_ior_func
-gm200_sor = {
+gm200_sor_hda = {
        .route = {
                .get = gm200_sor_route_get,
                .set = gm200_sor_route_set,
@@ -119,8 +119,42 @@ gm200_sor = {
        },
 };
 
+static const struct nvkm_ior_func
+gm200_sor = {
+       .route = {
+               .get = gm200_sor_route_get,
+               .set = gm200_sor_route_set,
+       },
+       .state = gf119_sor_state,
+       .power = nv50_sor_power,
+       .clock = gf119_sor_clock,
+       .hdmi = {
+               .ctrl = gk104_hdmi_ctrl,
+               .scdc = gm200_hdmi_scdc,
+       },
+       .dp = {
+               .lanes = { 0, 1, 2, 3 },
+               .links = gf119_sor_dp_links,
+               .power = g94_sor_dp_power,
+               .pattern = gm107_sor_dp_pattern,
+               .drive = gm200_sor_dp_drive,
+               .vcpi = gf119_sor_dp_vcpi,
+               .audio = gf119_sor_dp_audio,
+               .audio_sym = gf119_sor_dp_audio_sym,
+               .watermark = gf119_sor_dp_watermark,
+       },
+};
+
 int
 gm200_sor_new(struct nvkm_disp *disp, int id)
 {
+       struct nvkm_device *device = disp->engine.subdev.device;
+       u32 hda;
+
+       if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000))
+               hda = nvkm_rd32(device, 0x101034);
+
+       if (hda & BIT(id))
+               return nvkm_ior_new_(&gm200_sor_hda, disp, SOR, id);
        return nvkm_ior_new_(&gm200_sor, disp, SOR, id);
 }
index 94feb91b16d54e2b5bce0d7e66fcc76d2a8a3e11..c54f88317a07f5545b99c08221b0fa8ec69bc9a1 100644 (file)
@@ -22,7 +22,7 @@
 #include "ior.h"
 
 static const struct nvkm_ior_func
-gp100_sor = {
+gp100_sor_hda = {
        .route = {
                .get = gm200_sor_route_get,
                .set = gm200_sor_route_set,
@@ -52,8 +52,42 @@ gp100_sor = {
        },
 };
 
+static const struct nvkm_ior_func
+gp100_sor = {
+       .route = {
+               .get = gm200_sor_route_get,
+               .set = gm200_sor_route_set,
+       },
+       .state = gf119_sor_state,
+       .power = nv50_sor_power,
+       .clock = gf119_sor_clock,
+       .hdmi = {
+               .ctrl = gk104_hdmi_ctrl,
+               .scdc = gm200_hdmi_scdc,
+       },
+       .dp = {
+               .lanes = { 0, 1, 2, 3 },
+               .links = gf119_sor_dp_links,
+               .power = g94_sor_dp_power,
+               .pattern = gm107_sor_dp_pattern,
+               .drive = gm200_sor_dp_drive,
+               .vcpi = gf119_sor_dp_vcpi,
+               .audio = gf119_sor_dp_audio,
+               .audio_sym = gf119_sor_dp_audio_sym,
+               .watermark = gf119_sor_dp_watermark,
+       },
+};
+
 int
 gp100_sor_new(struct nvkm_disp *disp, int id)
 {
+       struct nvkm_device *device = disp->engine.subdev.device;
+       u32 hda;
+
+       if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000))
+               hda = nvkm_rd32(device, 0x10ebb0) >> 8;
+
+       if (hda & BIT(id))
+               return nvkm_ior_new_(&gp100_sor_hda, disp, SOR, id);
        return nvkm_ior_new_(&gp100_sor, disp, SOR, id);
 }
index d11a0dff10c66ae93d0fb457578e8cb6c37638da..4441187e8ec905f66f77f9515a4889e39edc7493 100644 (file)
@@ -78,7 +78,7 @@ gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state)
 }
 
 static const struct nvkm_ior_func
-gv100_sor = {
+gv100_sor_hda = {
        .route = {
                .get = gm200_sor_route_get,
                .set = gm200_sor_route_set,
@@ -107,9 +107,42 @@ gv100_sor = {
        },
 };
 
+static const struct nvkm_ior_func
+gv100_sor = {
+       .route = {
+               .get = gm200_sor_route_get,
+               .set = gm200_sor_route_set,
+       },
+       .state = gv100_sor_state,
+       .power = nv50_sor_power,
+       .clock = gf119_sor_clock,
+       .hdmi = {
+               .ctrl = gv100_hdmi_ctrl,
+               .scdc = gm200_hdmi_scdc,
+       },
+       .dp = {
+               .lanes = { 0, 1, 2, 3 },
+               .links = gf119_sor_dp_links,
+               .power = g94_sor_dp_power,
+               .pattern = gm107_sor_dp_pattern,
+               .drive = gm200_sor_dp_drive,
+               .audio = gv100_sor_dp_audio,
+               .audio_sym = gv100_sor_dp_audio_sym,
+               .watermark = gv100_sor_dp_watermark,
+       },
+};
+
 int
 gv100_sor_new(struct nvkm_disp *disp, int id)
 {
+       struct nvkm_device *device = disp->engine.subdev.device;
+       u32 hda;
+
+       if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000))
+               hda = nvkm_rd32(device, 0x118fb0) >> 8;
+
+       if (hda & BIT(id))
+               return nvkm_ior_new_(&gv100_sor_hda, disp, SOR, id);
        return nvkm_ior_new_(&gv100_sor, disp, SOR, id);
 }
 
index fa6d742512376730e6f2e9f5774a23ab2d8d63aa..59865a934c4b9d4e3e0c85ab4f47a0bd86b2073b 100644 (file)
@@ -62,7 +62,7 @@ tu102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
 }
 
 static const struct nvkm_ior_func
-tu102_sor = {
+tu102_sor_hda = {
        .route = {
                .get = gm200_sor_route_get,
                .set = gm200_sor_route_set,
@@ -92,8 +92,38 @@ tu102_sor = {
        },
 };
 
+static const struct nvkm_ior_func
+tu102_sor = {
+       .route = {
+               .get = gm200_sor_route_get,
+               .set = gm200_sor_route_set,
+       },
+       .state = gv100_sor_state,
+       .power = nv50_sor_power,
+       .clock = gf119_sor_clock,
+       .hdmi = {
+               .ctrl = gv100_hdmi_ctrl,
+               .scdc = gm200_hdmi_scdc,
+       },
+       .dp = {
+               .lanes = { 0, 1, 2, 3 },
+               .links = tu102_sor_dp_links,
+               .power = g94_sor_dp_power,
+               .pattern = gm107_sor_dp_pattern,
+               .drive = gm200_sor_dp_drive,
+               .vcpi = tu102_sor_dp_vcpi,
+               .audio = gv100_sor_dp_audio,
+               .audio_sym = gv100_sor_dp_audio_sym,
+               .watermark = gv100_sor_dp_watermark,
+       },
+};
+
 int
 tu102_sor_new(struct nvkm_disp *disp, int id)
 {
+       struct nvkm_device *device = disp->engine.subdev.device;
+       u32 hda = nvkm_rd32(device, 0x08a15c);
+       if (hda & BIT(id))
+               return nvkm_ior_new_(&tu102_sor_hda, disp, SOR, id);
        return nvkm_ior_new_(&tu102_sor, disp, SOR, id);
 }