drm/nouveau/disp: move HDA ELD method
authorBen Skeggs <bskeggs@redhat.com>
Wed, 1 Jun 2022 10:46:33 +0000 (20:46 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 8 Nov 2022 22:22:02 +0000 (08:22 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/include/nvif/cl5070.h
drivers/gpu/drm/nouveau/include/nvif/if0012.h
drivers/gpu/drm/nouveau/include/nvif/outp.h
drivers/gpu/drm/nouveau/nvif/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c

index edf8996..c61617a 100644 (file)
@@ -673,29 +673,33 @@ nv50_audio_component_fini(struct nouveau_drm *drm)
 /******************************************************************************
  * Audio
  *****************************************************************************/
+static bool
+nv50_audio_supported(struct drm_encoder *encoder)
+{
+       struct nv50_disp *disp = nv50_disp(encoder->dev);
+
+       if (disp->disp->object.oclass <= GT200_DISP ||
+           disp->disp->object.oclass == GT206_DISP)
+               return false;
+
+       return true;
+}
+
 static void
 nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
 {
        struct nouveau_drm *drm = nouveau_drm(encoder->dev);
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-       struct nv50_disp *disp = nv50_disp(encoder->dev);
        struct nvif_outp *outp = &nv_encoder->outp;
-       struct {
-               struct nv50_disp_mthd_v1 base;
-               struct nv50_disp_sor_hda_eld_v0 eld;
-       } args = {
-               .base.version = 1,
-               .base.method  = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
-               .base.hasht   = nv_encoder->dcb->hasht,
-               .base.hashm   = (0xf0ff & nv_encoder->dcb->hashm) |
-                               (0x0100 << nv_crtc->index),
-       };
+
+       if (!nv50_audio_supported(encoder))
+               return;
 
        mutex_lock(&drm->audio.lock);
        if (nv_encoder->audio.enabled) {
                nv_encoder->audio.enabled = false;
                nv_encoder->audio.connector = NULL;
-               nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
+               nvif_outp_hda_eld(&nv_encoder->outp, nv_crtc->index, NULL, 0);
        }
        mutex_unlock(&drm->audio.lock);
 
@@ -709,31 +713,15 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
 {
        struct nouveau_drm *drm = nouveau_drm(encoder->dev);
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-       struct nv50_disp *disp = nv50_disp(encoder->dev);
        struct nvif_outp *outp = &nv_encoder->outp;
-       struct __packed {
-               struct {
-                       struct nv50_disp_mthd_v1 mthd;
-                       struct nv50_disp_sor_hda_eld_v0 eld;
-               } base;
-               u8 data[sizeof(nv_connector->base.eld)];
-       } args = {
-               .base.mthd.version = 1,
-               .base.mthd.method  = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
-               .base.mthd.hasht   = nv_encoder->dcb->hasht,
-               .base.mthd.hashm   = (0xf0ff & nv_encoder->dcb->hashm) |
-                                    (0x0100 << nv_crtc->index),
-       };
 
-       if (!drm_detect_monitor_audio(nv_connector->edid))
+       if (!nv50_audio_supported(encoder) || !drm_detect_monitor_audio(nv_connector->edid))
                return;
 
        mutex_lock(&drm->audio.lock);
 
-       memcpy(args.data, nv_connector->base.eld, sizeof(args.data));
-
-       nvif_mthd(&disp->disp->object, 0, &args,
-                 sizeof(args.base) + drm_eld_size(args.data));
+       nvif_outp_hda_eld(&nv_encoder->outp, nv_crtc->index, nv_connector->base.eld,
+                         drm_eld_size(nv_connector->base.eld));
        nv_encoder->audio.enabled = true;
        nv_encoder->audio.connector = &nv_connector->base;
 
index 6389558..a713177 100644 (file)
@@ -28,7 +28,6 @@ struct nv50_disp_scanoutpos_v0 {
 
 struct nv50_disp_mthd_v1 {
        __u8  version;
-#define NV50_DISP_MTHD_V1_SOR_HDA_ELD                                      0x21
 #define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK                                  0x25
 #define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI                                  0x26
        __u8  method;
@@ -37,12 +36,6 @@ struct nv50_disp_mthd_v1 {
        __u8  pad06[2];
 };
 
-struct nv50_disp_sor_hda_eld_v0 {
-       __u8  version;
-       __u8  pad01[7];
-       __u8  data[];
-};
-
 struct nv50_disp_sor_dp_mst_link_v0 {
        __u8  version;
        __u8  state;
index 06ed372..938d384 100644 (file)
@@ -14,6 +14,7 @@ union nvif_outp_args {
 #define NVIF_OUTP_V0_ACQUIRE     0x01
 #define NVIF_OUTP_V0_RELEASE     0x02
 #define NVIF_OUTP_V0_INFOFRAME   0x03
+#define NVIF_OUTP_V0_HDA_ELD     0x04
 
 union nvif_outp_load_detect_args {
        struct nvif_outp_load_detect_v0 {
@@ -77,4 +78,13 @@ union nvif_outp_infoframe_args {
                __u8 data[];
        } v0;
 };
+
+union nvif_outp_hda_eld_args {
+       struct nvif_outp_hda_eld_v0 {
+               __u8  version;
+               __u8  head;
+               __u8  pad02[6];
+               __u8  data[];
+       } v0;
+};
 #endif
index dd7e603..c8879d3 100644 (file)
@@ -24,4 +24,5 @@ int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8);
 int nvif_outp_acquire_dp(struct nvif_outp *, bool hda);
 void nvif_outp_release(struct nvif_outp *);
 int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size);
+int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
 #endif
index 987bc3a..3a7c2d5 100644 (file)
 #include <nvif/class.h>
 
 int
+nvif_outp_hda_eld(struct nvif_outp *outp, int head, void *data, u32 size)
+{
+       struct {
+               struct nvif_outp_hda_eld_v0 mthd;
+               u8 data[128];
+       } args;
+       int ret;
+
+       if (WARN_ON(size > ARRAY_SIZE(args.data)))
+               return -EINVAL;
+
+       args.mthd.version = 0;
+       args.mthd.head = head;
+
+       memcpy(args.data, data, size);
+       ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDA_ELD, &args, sizeof(args.mthd) + size);
+       NVIF_ERRON(ret, &outp->object, "[HDA_ELD head:%d size:%d]", head, size);
+       return ret;
+}
+
+int
 nvif_outp_infoframe(struct nvif_outp *outp, u8 type, struct nvif_outp_infoframe_v0 *args, u32 size)
 {
        int ret;
index 9c481fa..a5bb15b 100644 (file)
@@ -91,39 +91,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
        }
 
        switch (mthd * !!outp) {
-       case NV50_DISP_MTHD_V1_SOR_HDA_ELD: {
-               union {
-                       struct nv50_disp_sor_hda_eld_v0 v0;
-               } *args = data;
-               struct nvkm_ior *ior = outp->ior;
-               int ret = -ENOSYS;
-
-               nvif_ioctl(object, "disp sor hda eld size %d\n", size);
-               if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
-                       nvif_ioctl(object, "disp sor hda eld vers %d\n",
-                                  args->v0.version);
-                       if (size > 0x60)
-                               return -E2BIG;
-               } else
-                       return ret;
-
-               if (!ior->hda)
-                       return -ENODEV;
-
-               if (size && args->v0.data[0]) {
-                       if (outp->info.type == DCB_OUTPUT_DP)
-                               ior->func->dp->audio(ior, hidx, true);
-                       ior->func->hda->hpd(ior, hidx, true);
-                       ior->func->hda->eld(ior, hidx, data, size);
-               } else {
-                       if (outp->info.type == DCB_OUTPUT_DP)
-                               ior->func->dp->audio(ior, hidx, false);
-                       ior->func->hda->hpd(ior, hidx, false);
-               }
-
-               return 0;
-       }
-               break;
        case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: {
                union {
                        struct nv50_disp_sor_dp_mst_link_v0 v0;
index f82100b..052b2d1 100644 (file)
 #include <nvif/if0012.h>
 
 static int
+nvkm_uoutp_mthd_hda_eld(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+       struct nvkm_ior *ior = outp->ior;
+       union nvif_outp_hda_eld_args *args = argv;
+
+       if (argc < sizeof(args->v0) || args->v0.version != 0)
+               return -ENOSYS;
+       argc -= sizeof(args->v0);
+
+       if (!ior->hda || !nvkm_head_find(outp->disp, args->v0.head))
+               return -EINVAL;
+       if (argc > 0x60)
+               return -E2BIG;
+
+       if (argc && args->v0.data[0]) {
+               if (outp->info.type == DCB_OUTPUT_DP)
+                       ior->func->dp->audio(ior, args->v0.head, true);
+               ior->func->hda->hpd(ior, args->v0.head, true);
+               ior->func->hda->eld(ior, args->v0.head, args->v0.data, argc);
+       } else {
+               if (outp->info.type == DCB_OUTPUT_DP)
+                       ior->func->dp->audio(ior, args->v0.head, false);
+               ior->func->hda->hpd(ior, args->v0.head, false);
+       }
+
+       return 0;
+}
+
+static int
 nvkm_uoutp_mthd_infoframe(struct nvkm_outp *outp, void *argv, u32 argc)
 {
        struct nvkm_ior *ior = outp->ior;
@@ -184,6 +213,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
        switch (mthd) {
        case NVIF_OUTP_V0_RELEASE    : return nvkm_uoutp_mthd_release    (outp, argv, argc);
        case NVIF_OUTP_V0_INFOFRAME  : return nvkm_uoutp_mthd_infoframe  (outp, argv, argc);
+       case NVIF_OUTP_V0_HDA_ELD    : return nvkm_uoutp_mthd_hda_eld    (outp, argv, argc);
        default:
                break;
        }