diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2020-06-03 11:43:23 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2020-06-04 14:23:21 +1000 |
commit | e6867ffa34340636252efe8e6b82be625c43d9b1 (patch) | |
tree | 35ad51cd57535d72c8b69b64040f01f79a0c4187 /drivers | |
parent | f24b6ae19fa257ea9b10a9389d0b7046b3efd97c (diff) |
drm/nouveau/disp: modify OR allocation policy to account for HDA requirements
Since GM200, SORs are no longer tied to a specific connector, and we
allocate them instead, with the assumption that all SORs are equally
capable.
However, there's a 1<->1 mapping between SOR and HDA pin widget, and
it turns out that it's possible for some widgets to be disabled...
In order to avoid picking a SOR without a valid pin widget, some new
rules need to be added.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c index b56224558a05..dcf08249374a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c @@ -121,14 +121,14 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type, * on HW, if any, in order to prevent unnecessary switching. */ list_for_each_entry(ior, &outp->disp->ior, head) { - if (!ior->identity && + if (!ior->identity && !!ior->func->hda.hpd == hda && !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->identity && + if (!ior->identity && !!ior->func->hda.hpd == hda && !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); @@ -138,7 +138,7 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type, * but will be released during the next modeset. */ list_for_each_entry(ior, &outp->disp->ior, head) { - if (!ior->identity && + if (!ior->identity && !!ior->func->hda.hpd == hda && !ior->asy.outp && ior->type == type && (ior->func->route.set || ior->id == __ffs(outp->info.or))) return nvkm_outp_acquire_ior(outp, user, ior); @@ -173,7 +173,25 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda) return nvkm_outp_acquire_ior(outp, user, ior); } - return nvkm_outp_acquire_hda(outp, type, user, true); + /* If we don't need HDA, first try to acquire an OR that doesn't + * support it to leave free the ones that do. + */ + if (!hda) { + if (!nvkm_outp_acquire_hda(outp, type, user, false)) + return 0; + + /* Use a HDA-supporting SOR anyway. */ + return nvkm_outp_acquire_hda(outp, type, user, true); + } + + /* We want HDA, try to acquire an OR that supports it. */ + if (!nvkm_outp_acquire_hda(outp, type, user, true)) + return 0; + + /* There weren't any free ORs that support HDA, grab one that + * doesn't and at least allow display to work still. + */ + return nvkm_outp_acquire_hda(outp, type, user, false); } void |