drm/nouveau/disp/gm200-: detect and potentially disable HDA support on some SORs
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>
This commit is contained in:
parent
9f9f54e887
commit
9b5ca547bb
@ -89,7 +89,7 @@ gm200_sor_route_get(struct nvkm_outp *outp, int *link)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct nvkm_ior_func
|
static const struct nvkm_ior_func
|
||||||
gm200_sor = {
|
gm200_sor_hda = {
|
||||||
.route = {
|
.route = {
|
||||||
.get = gm200_sor_route_get,
|
.get = gm200_sor_route_get,
|
||||||
.set = gm200_sor_route_set,
|
.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
|
int
|
||||||
gm200_sor_new(struct nvkm_disp *disp, int id)
|
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);
|
return nvkm_ior_new_(&gm200_sor, disp, SOR, id);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "ior.h"
|
#include "ior.h"
|
||||||
|
|
||||||
static const struct nvkm_ior_func
|
static const struct nvkm_ior_func
|
||||||
gp100_sor = {
|
gp100_sor_hda = {
|
||||||
.route = {
|
.route = {
|
||||||
.get = gm200_sor_route_get,
|
.get = gm200_sor_route_get,
|
||||||
.set = gm200_sor_route_set,
|
.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
|
int
|
||||||
gp100_sor_new(struct nvkm_disp *disp, int id)
|
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);
|
return nvkm_ior_new_(&gp100_sor, disp, SOR, id);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct nvkm_ior_func
|
static const struct nvkm_ior_func
|
||||||
gv100_sor = {
|
gv100_sor_hda = {
|
||||||
.route = {
|
.route = {
|
||||||
.get = gm200_sor_route_get,
|
.get = gm200_sor_route_get,
|
||||||
.set = gm200_sor_route_set,
|
.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
|
int
|
||||||
gv100_sor_new(struct nvkm_disp *disp, int id)
|
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);
|
return nvkm_ior_new_(&gv100_sor, disp, SOR, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ tu102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct nvkm_ior_func
|
static const struct nvkm_ior_func
|
||||||
tu102_sor = {
|
tu102_sor_hda = {
|
||||||
.route = {
|
.route = {
|
||||||
.get = gm200_sor_route_get,
|
.get = gm200_sor_route_get,
|
||||||
.set = gm200_sor_route_set,
|
.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
|
int
|
||||||
tu102_sor_new(struct nvkm_disp *disp, int id)
|
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);
|
return nvkm_ior_new_(&tu102_sor, disp, SOR, id);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user