Skip to content

Commit

Permalink
drm/nouveau/disp/gm200-: enforce identity-mapped SOR assignment for L…
Browse files Browse the repository at this point in the history
…VDS/eDP panels

Fixes eDP backlight issues on more recent laptops.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Sep 6, 2018
1 parent e04cfdc commit 53b0cc4
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 3 deletions.
14 changes: 14 additions & 0 deletions drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct nvkm_ior {
char name[8];

struct list_head head;
bool identity;

struct nvkm_ior_state {
struct nvkm_outp *outp;
Expand Down
15 changes: 12 additions & 3 deletions drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct nvkm_outp {

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

/* Assembly state. */
#define NVKM_OUTP_PRIV 1
Expand Down

0 comments on commit 53b0cc4

Please sign in to comment.