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

Commit 53b0cc46 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/disp/gm200-: enforce identity-mapped SOR assignment for LVDS/eDP panels



Fixes eDP backlight issues on more recent laptops.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent e04cfdc9
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -275,6 +275,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
	struct nvkm_outp *outp, *outt, *pair;
	struct nvkm_conn *conn;
	struct nvkm_head *head;
	struct nvkm_ior *ior;
	struct nvbios_connE connE;
	struct dcb_output dcbE;
	u8  hpd = 0, ver, hdr;
@@ -399,6 +400,19 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
			return ret;
	}

	/* Enforce identity-mapped SOR assignment for panels, which have
	 * certain bits (ie. backlight controls) wired to a specific SOR.
	 */
	list_for_each_entry(outp, &disp->outp, head) {
		if (outp->conn->info.type == DCB_CONNECTOR_LVDS ||
		    outp->conn->info.type == DCB_CONNECTOR_eDP) {
			ior = nvkm_ior_find(disp, SOR, ffs(outp->info.or) - 1);
			if (!WARN_ON(!ior))
				ior->identity = true;
			outp->identity = true;
		}
	}

	i = 0;
	list_for_each_entry(head, &disp->head, head)
		i = max(i, head->id + 1);
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ struct nvkm_ior {
	char name[8];

	struct list_head head;
	bool identity;

	struct nvkm_ior_state {
		struct nvkm_outp *outp;
+12 −3
Original line number Diff line number Diff line
@@ -129,17 +129,26 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user)
	if (proto == UNKNOWN)
		return -ENOSYS;

	/* Deal with panels requiring identity-mapped SOR assignment. */
	if (outp->identity) {
		ior = nvkm_ior_find(outp->disp, SOR, ffs(outp->info.or) - 1);
		if (WARN_ON(!ior))
			return -ENOSPC;
		return nvkm_outp_acquire_ior(outp, user, ior);
	}

	/* First preference is to reuse the OR that is currently armed
	 * on HW, if any, in order to prevent unnecessary switching.
	 */
	list_for_each_entry(ior, &outp->disp->ior, head) {
		if (!ior->asy.outp && ior->arm.outp == outp)
		if (!ior->identity && !ior->asy.outp && ior->arm.outp == outp)
			return nvkm_outp_acquire_ior(outp, user, ior);
	}

	/* Failing that, a completely unused OR is the next best thing. */
	list_for_each_entry(ior, &outp->disp->ior, head) {
		if (!ior->asy.outp && ior->type == type && !ior->arm.outp &&
		if (!ior->identity &&
		    !ior->asy.outp && ior->type == type && !ior->arm.outp &&
		    (ior->func->route.set || ior->id == __ffs(outp->info.or)))
			return nvkm_outp_acquire_ior(outp, user, ior);
	}
@@ -148,7 +157,7 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user)
	 * but will be released during the next modeset.
	 */
	list_for_each_entry(ior, &outp->disp->ior, head) {
		if (!ior->asy.outp && ior->type == type &&
		if (!ior->identity && !ior->asy.outp && ior->type == type &&
		    (ior->func->route.set || ior->id == __ffs(outp->info.or)))
			return nvkm_outp_acquire_ior(outp, user, ior);
	}
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ struct nvkm_outp {

	struct list_head head;
	struct nvkm_conn *conn;
	bool identity;

	/* Assembly state. */
#define NVKM_OUTP_PRIV 1