Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ae5a62b authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/disp/dp: fix tmds passthrough on dp connector



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 8777c5c1
Loading
Loading
Loading
Loading
+33 −5
Original line number Original line Diff line number Diff line
@@ -1171,7 +1171,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
	return NULL;
	return NULL;
}
}


static bool
static struct nvkm_output *
exec_script(struct nv50_disp_priv *priv, int head, int id)
exec_script(struct nv50_disp_priv *priv, int head, int id)
{
{
	struct nouveau_bios *bios = nouveau_bios(priv);
	struct nouveau_bios *bios = nouveau_bios(priv);
@@ -1208,7 +1208,7 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
	}
	}


	if (!(ctrl & (1 << head)))
	if (!(ctrl & (1 << head)))
		return false;
		return NULL;
	i--;
	i--;


	outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
	outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
@@ -1222,10 +1222,10 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
			.execute = 1,
			.execute = 1,
		};
		};


		return nvbios_exec(&init) == 0;
		nvbios_exec(&init);
	}
	}


	return false;
	return outp;
}
}


static struct nvkm_output *
static struct nvkm_output *
@@ -1325,7 +1325,35 @@ nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head)
static void
static void
nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head)
nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head)
{
{
	exec_script(priv, head, 2);
	struct nvkm_output *outp = exec_script(priv, head, 2);

	/* the binary driver does this outside of the supervisor handling
	 * (after the third supervisor from a detach).  we (currently?)
	 * allow both detach/attach to happen in the same set of
	 * supervisor interrupts, so it would make sense to execute this
	 * (full power down?) script after all the detach phases of the
	 * supervisor handling.  like with training if needed from the
	 * second supervisor, nvidia doesn't do this, so who knows if it's
	 * entirely safe, but it does appear to work..
	 *
	 * without this script being run, on some configurations i've
	 * seen, switching from DP to TMDS on a DP connector may result
	 * in a blank screen (SOR_PWR off/on can restore it)
	 */
	if (outp && outp->info.type == DCB_OUTPUT_DP) {
		struct nvkm_output_dp *outpdp = (void *)outp;
		struct nvbios_init init = {
			.subdev = nv_subdev(priv),
			.bios = nouveau_bios(priv),
			.outp = &outp->info,
			.crtc = head,
			.offset = outpdp->info.script[4],
			.execute = 1,
		};

		nvbios_exec(&init);
		atomic_set(&outpdp->lt.done, 0);
	}
}
}


static void
static void
+21 −5
Original line number Original line Diff line number Diff line
@@ -962,7 +962,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
	return NULL;
	return NULL;
}
}


static bool
static struct nvkm_output *
exec_script(struct nv50_disp_priv *priv, int head, int id)
exec_script(struct nv50_disp_priv *priv, int head, int id)
{
{
	struct nouveau_bios *bios = nouveau_bios(priv);
	struct nouveau_bios *bios = nouveau_bios(priv);
@@ -979,7 +979,7 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
	}
	}


	if (or == 8)
	if (or == 8)
		return false;
		return NULL;


	outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
	outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
	if (outp) {
	if (outp) {
@@ -992,10 +992,10 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
			.execute = 1,
			.execute = 1,
		};
		};


		return nvbios_exec(&init) == 0;
		nvbios_exec(&init);
	}
	}


	return false;
	return outp;
}
}


static struct nvkm_output *
static struct nvkm_output *
@@ -1069,7 +1069,23 @@ nvd0_disp_intr_unk1_0(struct nv50_disp_priv *priv, int head)
static void
static void
nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head)
nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head)
{
{
	exec_script(priv, head, 2);
	struct nvkm_output *outp = exec_script(priv, head, 2);

	/* see note in nv50_disp_intr_unk20_0() */
	if (outp && outp->info.type == DCB_OUTPUT_DP) {
		struct nvkm_output_dp *outpdp = (void *)outp;
		struct nvbios_init init = {
			.subdev = nv_subdev(priv),
			.bios = nouveau_bios(priv),
			.outp = &outp->info,
			.crtc = head,
			.offset = outpdp->info.script[4],
			.execute = 1,
		};

		nvbios_exec(&init);
		atomic_set(&outpdp->lt.done, 0);
	}
}
}


static void
static void