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) ...@@ -275,6 +275,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
struct nvkm_outp *outp, *outt, *pair; struct nvkm_outp *outp, *outt, *pair;
struct nvkm_conn *conn; struct nvkm_conn *conn;
struct nvkm_head *head; struct nvkm_head *head;
struct nvkm_ior *ior;
struct nvbios_connE connE; struct nvbios_connE connE;
struct dcb_output dcbE; struct dcb_output dcbE;
u8 hpd = 0, ver, hdr; u8 hpd = 0, ver, hdr;
...@@ -399,6 +400,19 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) ...@@ -399,6 +400,19 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
return ret; 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; i = 0;
list_for_each_entry(head, &disp->head, head) list_for_each_entry(head, &disp->head, head)
i = max(i, head->id + 1); i = max(i, head->id + 1);
......
...@@ -16,6 +16,7 @@ struct nvkm_ior { ...@@ -16,6 +16,7 @@ struct nvkm_ior {
char name[8]; char name[8];
struct list_head head; struct list_head head;
bool identity;
struct nvkm_ior_state { struct nvkm_ior_state {
struct nvkm_outp *outp; struct nvkm_outp *outp;
......
...@@ -129,17 +129,26 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user) ...@@ -129,17 +129,26 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user)
if (proto == UNKNOWN) if (proto == UNKNOWN)
return -ENOSYS; 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 /* First preference is to reuse the OR that is currently armed
* on HW, if any, in order to prevent unnecessary switching. * on HW, if any, in order to prevent unnecessary switching.
*/ */
list_for_each_entry(ior, &outp->disp->ior, head) { 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); return nvkm_outp_acquire_ior(outp, user, ior);
} }
/* Failing that, a completely unused OR is the next best thing. */ /* Failing that, a completely unused OR is the next best thing. */
list_for_each_entry(ior, &outp->disp->ior, head) { 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))) (ior->func->route.set || ior->id == __ffs(outp->info.or)))
return nvkm_outp_acquire_ior(outp, user, ior); return nvkm_outp_acquire_ior(outp, user, ior);
} }
...@@ -148,7 +157,7 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user) ...@@ -148,7 +157,7 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user)
* but will be released during the next modeset. * but will be released during the next modeset.
*/ */
list_for_each_entry(ior, &outp->disp->ior, head) { 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))) (ior->func->route.set || ior->id == __ffs(outp->info.or)))
return nvkm_outp_acquire_ior(outp, user, ior); return nvkm_outp_acquire_ior(outp, user, ior);
} }
......
...@@ -16,6 +16,7 @@ struct nvkm_outp { ...@@ -16,6 +16,7 @@ struct nvkm_outp {
struct list_head head; struct list_head head;
struct nvkm_conn *conn; struct nvkm_conn *conn;
bool identity;
/* Assembly state. */ /* Assembly state. */
#define NVKM_OUTP_PRIV 1 #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