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

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
......@@ -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);
......
......@@ -16,6 +16,7 @@ struct nvkm_ior {
char name[8];
struct list_head head;
bool identity;
struct nvkm_ior_state {
struct nvkm_outp *outp;
......
......@@ -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);
}
......
......@@ -16,6 +16,7 @@ struct nvkm_outp {
struct list_head head;
struct nvkm_conn *conn;
bool identity;
/* Assembly state. */
#define NVKM_OUTP_PRIV 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment