From 61598093bbdd283a7edc367d900f223070ead8d2 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 07:43:03 +0000 Subject: [PATCH] add ax88772C AX88772C_eeprom_tools --- kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c | 75 +++++++++++++++++++++++++++++-------- 1 files changed, 58 insertions(+), 17 deletions(-) diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c index 4b1c72f..129982f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c @@ -112,8 +112,35 @@ return 0; } +static inline int +nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type, + u8 user, bool hda) +{ + struct nvkm_ior *ior; + + /* Failing that, a completely unused OR is the next best thing. */ + list_for_each_entry(ior, &outp->disp->ior, head) { + 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); + } + + /* Last resort is to assign an OR that's already active on HW, + * but will be released during the next modeset. + */ + list_for_each_entry(ior, &outp->disp->ior, head) { + 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); + } + + return -ENOSPC; +} + int -nvkm_outp_acquire(struct nvkm_outp *outp, u8 user) +nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda) { struct nvkm_ior *ior = outp->ior; enum nvkm_ior_proto proto; @@ -142,28 +169,42 @@ * on HW, if any, in order to prevent unnecessary switching. */ list_for_each_entry(ior, &outp->disp->ior, head) { - if (!ior->identity && !ior->asy.outp && ior->arm.outp == outp) + if (!ior->identity && !ior->asy.outp && ior->arm.outp == outp) { + /*XXX: For various complicated reasons, we can't outright switch + * the boot-time OR on the first modeset without some fairly + * invasive changes. + * + * The systems that were fixed by modifying the OR selection + * code to account for HDA support shouldn't regress here as + * the HDA-enabled ORs match the relevant output's pad macro + * index, and the firmware seems to select an OR this way. + * + * This warning is to make it obvious if that proves wrong. + */ + WARN_ON(hda && !ior->func->hda.hpd); 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 && - !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); - } - - /* Last resort is to assign an OR that's already active on HW, - * but will be released during the next modeset. + /* If we don't need HDA, first try to acquire an OR that doesn't + * support it to leave free the ones that do. */ - list_for_each_entry(ior, &outp->disp->ior, head) { - 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); + 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); } - return -ENOSPC; + /* 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 -- Gitblit v1.6.2