Commit 9b5ca547 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent 9f9f54e8
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -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);
}
+35 −1
Original line number Diff line number Diff line
@@ -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);
}
+34 −1
Original line number Diff line number Diff line
@@ -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);
}

+31 −1
Original line number Diff line number Diff line
@@ -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);
}