drm/nouveau/disp: move outp/conn construction to chipset code
authorBen Skeggs <bskeggs@redhat.com>
Tue, 19 Sep 2023 21:56:31 +0000 (17:56 -0400)
committerLyude Paul <lyude@redhat.com>
Tue, 19 Sep 2023 22:22:23 +0000 (18:22 -0400)
- pre-nv5x doesn't use any of this, has its own version DRM-side
- preparation for GSP-RM

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Acked-by: Danilo Krummrich <me@dakr.org>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230919220442.202488-37-lyude@redhat.com
drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c

index 73104b5..1dbe68f 100644 (file)
  */
 #include "priv.h"
 #include "conn.h"
-#include "dp.h"
 #include "head.h"
 #include "ior.h"
 #include "outp.h"
 
 #include <core/client.h>
 #include <core/ramht.h>
-#include <subdev/bios.h>
-#include <subdev/bios/dcb.h>
 
 #include <nvif/class.h>
 #include <nvif/cl0046.h>
@@ -159,123 +156,11 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
 {
        struct nvkm_disp *disp = nvkm_disp(engine);
        struct nvkm_subdev *subdev = &disp->engine.subdev;
-       struct nvkm_bios *bios = subdev->device->bios;
-       struct nvkm_outp *outp, *outt, *pair;
-       struct nvkm_conn *conn;
+       struct nvkm_outp *outp;
        struct nvkm_head *head;
        struct nvkm_ior *ior;
-       struct nvbios_connE connE;
-       struct dcb_output dcbE;
-       u8  hpd = 0, ver, hdr;
-       u32 data;
        int ret, i;
 
-       /* Create output path objects for each VBIOS display path. */
-       i = -1;
-       while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE))) {
-               if (ver < 0x40) /* No support for chipsets prior to NV50. */
-                       break;
-               if (dcbE.type == DCB_OUTPUT_UNUSED)
-                       continue;
-               if (dcbE.type == DCB_OUTPUT_EOL)
-                       break;
-               outp = NULL;
-
-               switch (dcbE.type) {
-               case DCB_OUTPUT_ANALOG:
-               case DCB_OUTPUT_TV:
-               case DCB_OUTPUT_TMDS:
-               case DCB_OUTPUT_LVDS:
-                       ret = nvkm_outp_new(disp, i, &dcbE, &outp);
-                       break;
-               case DCB_OUTPUT_DP:
-                       ret = nvkm_dp_new(disp, i, &dcbE, &outp);
-                       break;
-               case DCB_OUTPUT_WFD:
-                       /* No support for WFD yet. */
-                       ret = -ENODEV;
-                       continue;
-               default:
-                       nvkm_warn(subdev, "dcb %d type %d unknown\n",
-                                 i, dcbE.type);
-                       continue;
-               }
-
-               if (ret) {
-                       if (outp) {
-                               if (ret != -ENODEV)
-                                       OUTP_ERR(outp, "ctor failed: %d", ret);
-                               else
-                                       OUTP_DBG(outp, "not supported");
-                               nvkm_outp_del(&outp);
-                               continue;
-                       }
-                       nvkm_error(subdev, "failed to create outp %d\n", i);
-                       continue;
-               }
-
-               list_add_tail(&outp->head, &disp->outps);
-               hpd = max(hpd, (u8)(dcbE.connector + 1));
-       }
-
-       /* Create connector objects based on available output paths. */
-       list_for_each_entry_safe(outp, outt, &disp->outps, head) {
-               /* VBIOS data *should* give us the most useful information. */
-               data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr,
-                                    &connE);
-
-               /* No bios connector data... */
-               if (!data) {
-                       /* Heuristic: anything with the same ccb index is
-                        * considered to be on the same connector, any
-                        * output path without an associated ccb entry will
-                        * be put on its own connector.
-                        */
-                       int ccb_index = outp->info.i2c_index;
-                       if (ccb_index != 0xf) {
-                               list_for_each_entry(pair, &disp->outps, head) {
-                                       if (pair->info.i2c_index == ccb_index) {
-                                               outp->conn = pair->conn;
-                                               break;
-                                       }
-                               }
-                       }
-
-                       /* Connector shared with another output path. */
-                       if (outp->conn)
-                               continue;
-
-                       memset(&connE, 0x00, sizeof(connE));
-                       connE.type = DCB_CONNECTOR_NONE;
-                       i = -1;
-               } else {
-                       i = outp->info.connector;
-               }
-
-               /* Check that we haven't already created this connector. */
-               list_for_each_entry(conn, &disp->conns, head) {
-                       if (conn->index == outp->info.connector) {
-                               outp->conn = conn;
-                               break;
-                       }
-               }
-
-               if (outp->conn)
-                       continue;
-
-               /* Apparently we need to create a new one! */
-               ret = nvkm_conn_new(disp, i, &connE, &outp->conn);
-               if (ret) {
-                       nvkm_error(subdev, "failed to create outp %d conn: %d\n", outp->index, ret);
-                       nvkm_conn_del(&outp->conn);
-                       list_del(&outp->head);
-                       nvkm_outp_del(&outp);
-                       continue;
-               }
-
-               list_add_tail(&outp->conn->head, &disp->conns);
-       }
-
        if (disp->func->oneinit) {
                ret = disp->func->oneinit(disp);
                if (ret)
index e9d0a9b..7343b24 100644 (file)
@@ -23,7 +23,9 @@
  */
 #include "priv.h"
 #include "chan.h"
+#include "conn.h"
 #include "head.h"
+#include "dp.h"
 #include "ior.h"
 #include "outp.h"
 
@@ -1581,7 +1583,14 @@ nv50_disp_oneinit(struct nvkm_disp *disp)
        const struct nvkm_disp_func *func = disp->func;
        struct nvkm_subdev *subdev = &disp->engine.subdev;
        struct nvkm_device *device = subdev->device;
+       struct nvkm_bios *bios = device->bios;
+       struct nvkm_outp *outp, *outt, *pair;
+       struct nvkm_conn *conn;
        int ret, i;
+       u8  ver, hdr;
+       u32 data;
+       struct dcb_output dcbE;
+       struct nvbios_connE connE;
 
        if (func->wndw.cnt) {
                disp->wndw.nr = func->wndw.cnt(disp, &disp->wndw.mask);
@@ -1628,8 +1637,117 @@ nv50_disp_oneinit(struct nvkm_disp *disp)
        if (ret)
                return ret;
 
-       return nvkm_ramht_new(device, func->ramht_size ? func->ramht_size :
-                             0x1000, 0, disp->inst, &disp->ramht);
+       ret = nvkm_ramht_new(device, func->ramht_size ? func->ramht_size : 0x1000, 0, disp->inst,
+                            &disp->ramht);
+       if (ret)
+               return ret;
+
+       /* Create output path objects for each VBIOS display path. */
+       i = -1;
+       while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE))) {
+               if (WARN_ON((ver & 0xf0) != 0x40))
+                       return -EINVAL;
+               if (dcbE.type == DCB_OUTPUT_UNUSED)
+                       continue;
+               if (dcbE.type == DCB_OUTPUT_EOL)
+                       break;
+               outp = NULL;
+
+               switch (dcbE.type) {
+               case DCB_OUTPUT_ANALOG:
+               case DCB_OUTPUT_TV:
+               case DCB_OUTPUT_TMDS:
+               case DCB_OUTPUT_LVDS:
+                       ret = nvkm_outp_new(disp, i, &dcbE, &outp);
+                       break;
+               case DCB_OUTPUT_DP:
+                       ret = nvkm_dp_new(disp, i, &dcbE, &outp);
+                       break;
+               case DCB_OUTPUT_WFD:
+                       /* No support for WFD yet. */
+                       ret = -ENODEV;
+                       continue;
+               default:
+                       nvkm_warn(subdev, "dcb %d type %d unknown\n",
+                                 i, dcbE.type);
+                       continue;
+               }
+
+               if (ret) {
+                       if (outp) {
+                               if (ret != -ENODEV)
+                                       OUTP_ERR(outp, "ctor failed: %d", ret);
+                               else
+                                       OUTP_DBG(outp, "not supported");
+                               nvkm_outp_del(&outp);
+                               continue;
+                       }
+                       nvkm_error(subdev, "failed to create outp %d\n", i);
+                       continue;
+               }
+
+               list_add_tail(&outp->head, &disp->outps);
+       }
+
+       /* Create connector objects based on available output paths. */
+       list_for_each_entry_safe(outp, outt, &disp->outps, head) {
+               /* VBIOS data *should* give us the most useful information. */
+               data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr,
+                                    &connE);
+
+               /* No bios connector data... */
+               if (!data) {
+                       /* Heuristic: anything with the same ccb index is
+                        * considered to be on the same connector, any
+                        * output path without an associated ccb entry will
+                        * be put on its own connector.
+                        */
+                       int ccb_index = outp->info.i2c_index;
+                       if (ccb_index != 0xf) {
+                               list_for_each_entry(pair, &disp->outps, head) {
+                                       if (pair->info.i2c_index == ccb_index) {
+                                               outp->conn = pair->conn;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       /* Connector shared with another output path. */
+                       if (outp->conn)
+                               continue;
+
+                       memset(&connE, 0x00, sizeof(connE));
+                       connE.type = DCB_CONNECTOR_NONE;
+                       i = -1;
+               } else {
+                       i = outp->info.connector;
+               }
+
+               /* Check that we haven't already created this connector. */
+               list_for_each_entry(conn, &disp->conns, head) {
+                       if (conn->index == outp->info.connector) {
+                               outp->conn = conn;
+                               break;
+                       }
+               }
+
+               if (outp->conn)
+                       continue;
+
+               /* Apparently we need to create a new one! */
+               ret = nvkm_conn_new(disp, i, &connE, &outp->conn);
+               if (ret) {
+                       nvkm_error(subdev, "failed to create outp %d conn: %d\n", outp->index, ret);
+                       nvkm_conn_del(&outp->conn);
+                       list_del(&outp->head);
+                       nvkm_outp_del(&outp);
+                       continue;
+               }
+
+               list_add_tail(&outp->conn->head, &disp->conns);
+       }
+
+       return 0;
 }
 
 static const struct nvkm_disp_func