drm/nouveau/kms/nv50-: create connectors based on nvkm info
authorBen Skeggs <bskeggs@redhat.com>
Tue, 19 Sep 2023 21:56:37 +0000 (17:56 -0400)
committerLyude Paul <lyude@redhat.com>
Tue, 19 Sep 2023 22:22:27 +0000 (18:22 -0400)
- 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-43-lyude@redhat.com
drivers/gpu/drm/nouveau/dispnv04/disp.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/include/nvif/conn.h
drivers/gpu/drm/nouveau/include/nvif/if0011.h
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_connector.h
drivers/gpu/drm/nouveau/nvif/conn.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c

index e9ac3fb27ff785ea4a32895d2d15ea3b0b350ead..13705c5f1497329a03d754ab9bfaacb6209de4b2 100644 (file)
@@ -256,7 +256,7 @@ nv04_display_create(struct drm_device *dev)
        for (i = 0; i < dcb->entries; i++) {
                struct dcb_output *dcbent = &dcb->entry[i];
 
-               connector = nouveau_connector_create(dev, dcbent);
+               connector = nouveau_connector_create(dev, dcbent->connector);
                if (IS_ERR(connector))
                        continue;
 
index 26d59346703e3c61af740eefd22c332f0d9784f3..e2fa748e66f16d21c54cfbf0ea00fb2fe9f73461 100644 (file)
@@ -2788,7 +2788,7 @@ nv50_display_create(struct drm_device *dev)
                        continue;
                }
 
-               connector = nouveau_connector_create(dev, dcbe);
+               connector = nouveau_connector_create(dev, dcbe->connector);
                if (IS_ERR(connector)) {
                        nvif_outp_dtor(&outp->outp);
                        kfree(outp);
index 8a6017a35897674780e8566a168ca7c0923a4061..406c12a111f9daf698bae7b8fe967fafbeba1d4a 100644 (file)
@@ -7,6 +7,21 @@ struct nvif_disp;
 
 struct nvif_conn {
        struct nvif_object object;
+       u32 id;
+
+       struct {
+               enum {
+                       NVIF_CONN_VGA,
+                       NVIF_CONN_TV,
+                       NVIF_CONN_DVI_I,
+                       NVIF_CONN_DVI_D,
+                       NVIF_CONN_LVDS,
+                       NVIF_CONN_LVDS_SPWG,
+                       NVIF_CONN_HDMI,
+                       NVIF_CONN_DP,
+                       NVIF_CONN_EDP,
+               } type;
+       } info;
 };
 
 int nvif_conn_ctor(struct nvif_disp *, const char *name, int id, struct nvif_conn *);
index 0c25288a5a789865112ce9a39d0dad6f6bbc8c47..3ed0ddd75bd8f9da25f2ed815552848ca9e56d3d 100644 (file)
@@ -7,6 +7,16 @@ union nvif_conn_args {
                __u8 version;
                __u8 id;        /* DCB connector table index. */
                __u8 pad02[6];
+#define NVIF_CONN_V0_VGA       0x00
+#define NVIF_CONN_V0_TV        0x01
+#define NVIF_CONN_V0_DVI_I     0x02
+#define NVIF_CONN_V0_DVI_D     0x03
+#define NVIF_CONN_V0_LVDS      0x04
+#define NVIF_CONN_V0_LVDS_SPWG 0x05
+#define NVIF_CONN_V0_HDMI      0x06
+#define NVIF_CONN_V0_DP        0x07
+#define NVIF_CONN_V0_EDP       0x08
+               __u8 type;
        } v0;
 };
 
index 73657736ce8380dfb0d520841fb9fd1a90746dac..21cc8dfcb7addf2d98e2528cd8aff2edd8ffd144 100644 (file)
@@ -1275,15 +1275,13 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
 }
 
 struct drm_connector *
-nouveau_connector_create(struct drm_device *dev,
-                        const struct dcb_output *dcbe)
+nouveau_connector_create(struct drm_device *dev, int index)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_display *disp = nouveau_display(dev);
        struct nouveau_connector *nv_connector = NULL;
        struct drm_connector *connector;
        struct drm_connector_list_iter conn_iter;
-       int index = dcbe->connector;
        int type, ret = 0;
        bool dummy;
 
@@ -1305,70 +1303,76 @@ nouveau_connector_create(struct drm_device *dev,
        nv_connector->index = index;
        INIT_WORK(&nv_connector->irq_work, nouveau_dp_irq);
 
-       /* attempt to parse vbios connector type and hotplug gpio */
-       nv_connector->dcb = olddcb_conn(dev, index);
-       if (nv_connector->dcb) {
-               u32 entry = ROM16(nv_connector->dcb[0]);
-               if (olddcb_conntab(dev)[3] >= 4)
-                       entry |= (u32)ROM16(nv_connector->dcb[2]) << 16;
-
-               nv_connector->type = nv_connector->dcb[0];
-               if (drm_conntype_from_dcb(nv_connector->type) ==
-                                         DRM_MODE_CONNECTOR_Unknown) {
-                       NV_WARN(drm, "unknown connector type %02x\n",
-                               nv_connector->type);
-                       nv_connector->type = DCB_CONNECTOR_NONE;
+       if (disp->disp.conn_mask & BIT(nv_connector->index)) {
+               ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index,
+                                    &nv_connector->conn);
+               if (ret) {
+                       kfree(nv_connector);
+                       return ERR_PTR(ret);
                }
 
-               /* Gigabyte NX85T */
-               if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) {
-                       if (nv_connector->type == DCB_CONNECTOR_HDMI_1)
-                               nv_connector->type = DCB_CONNECTOR_DVI_I;
+               switch (nv_connector->conn.info.type) {
+               case NVIF_CONN_VGA      : type = DCB_CONNECTOR_VGA; break;
+               case NVIF_CONN_DVI_I    : type = DCB_CONNECTOR_DVI_I; break;
+               case NVIF_CONN_DVI_D    : type = DCB_CONNECTOR_DVI_D; break;
+               case NVIF_CONN_LVDS     : type = DCB_CONNECTOR_LVDS; break;
+               case NVIF_CONN_LVDS_SPWG: type = DCB_CONNECTOR_LVDS_SPWG; break;
+               case NVIF_CONN_DP       : type = DCB_CONNECTOR_DP; break;
+               case NVIF_CONN_EDP      : type = DCB_CONNECTOR_eDP; break;
+               case NVIF_CONN_HDMI     : type = DCB_CONNECTOR_HDMI_0; break;
+               default:
+                       WARN_ON(1);
+                       return NULL;
                }
 
-               /* Gigabyte GV-NX86T512H */
-               if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) {
-                       if (nv_connector->type == DCB_CONNECTOR_HDMI_1)
-                               nv_connector->type = DCB_CONNECTOR_DVI_I;
-               }
+               nv_connector->type = type;
        } else {
-               nv_connector->type = DCB_CONNECTOR_NONE;
-       }
+               u8 *dcb = olddcb_conn(dev, nv_connector->index);
 
-       /* no vbios data, or an unknown dcb connector type - attempt to
-        * figure out something suitable ourselves
-        */
-       if (nv_connector->type == DCB_CONNECTOR_NONE) {
-               struct nouveau_drm *drm = nouveau_drm(dev);
-               struct dcb_table *dcbt = &drm->vbios.dcb;
-               u32 encoders = 0;
-               int i;
-
-               for (i = 0; i < dcbt->entries; i++) {
-                       if (dcbt->entry[i].connector == nv_connector->index)
-                               encoders |= (1 << dcbt->entry[i].type);
+               if (dcb)
+                       nv_connector->type = dcb[0];
+               else
+                       nv_connector->type = DCB_CONNECTOR_NONE;
+
+               /* attempt to parse vbios connector type and hotplug gpio */
+               if (nv_connector->type != DCB_CONNECTOR_NONE) {
+                       if (drm_conntype_from_dcb(nv_connector->type) ==
+                                                 DRM_MODE_CONNECTOR_Unknown) {
+                               NV_WARN(drm, "unknown connector type %02x\n",
+                                       nv_connector->type);
+                               nv_connector->type = DCB_CONNECTOR_NONE;
+                       }
                }
 
-               if (encoders & (1 << DCB_OUTPUT_DP)) {
-                       if (encoders & (1 << DCB_OUTPUT_TMDS))
-                               nv_connector->type = DCB_CONNECTOR_DP;
-                       else
-                               nv_connector->type = DCB_CONNECTOR_eDP;
-               } else
-               if (encoders & (1 << DCB_OUTPUT_TMDS)) {
-                       if (encoders & (1 << DCB_OUTPUT_ANALOG))
-                               nv_connector->type = DCB_CONNECTOR_DVI_I;
-                       else
-                               nv_connector->type = DCB_CONNECTOR_DVI_D;
-               } else
-               if (encoders & (1 << DCB_OUTPUT_ANALOG)) {
-                       nv_connector->type = DCB_CONNECTOR_VGA;
-               } else
-               if (encoders & (1 << DCB_OUTPUT_LVDS)) {
-                       nv_connector->type = DCB_CONNECTOR_LVDS;
-               } else
-               if (encoders & (1 << DCB_OUTPUT_TV)) {
-                       nv_connector->type = DCB_CONNECTOR_TV_0;
+               /* no vbios data, or an unknown dcb connector type - attempt to
+                * figure out something suitable ourselves
+                */
+               if (nv_connector->type == DCB_CONNECTOR_NONE &&
+                   !WARN_ON(drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA)) {
+                       struct dcb_table *dcbt = &drm->vbios.dcb;
+                       u32 encoders = 0;
+                       int i;
+
+                       for (i = 0; i < dcbt->entries; i++) {
+                               if (dcbt->entry[i].connector == nv_connector->index)
+                                       encoders |= (1 << dcbt->entry[i].type);
+                       }
+
+                       if (encoders & (1 << DCB_OUTPUT_TMDS)) {
+                               if (encoders & (1 << DCB_OUTPUT_ANALOG))
+                                       nv_connector->type = DCB_CONNECTOR_DVI_I;
+                               else
+                                       nv_connector->type = DCB_CONNECTOR_DVI_D;
+                       } else
+                       if (encoders & (1 << DCB_OUTPUT_ANALOG)) {
+                               nv_connector->type = DCB_CONNECTOR_VGA;
+                       } else
+                       if (encoders & (1 << DCB_OUTPUT_LVDS)) {
+                               nv_connector->type = DCB_CONNECTOR_LVDS;
+                       } else
+                       if (encoders & (1 << DCB_OUTPUT_TV)) {
+                               nv_connector->type = DCB_CONNECTOR_TV_0;
+                       }
                }
        }
 
@@ -1414,14 +1418,7 @@ nouveau_connector_create(struct drm_device *dev,
        drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
        connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
-       if (nv_connector->dcb && (disp->disp.conn_mask & BIT(nv_connector->index))) {
-               ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index,
-                                    &nv_connector->conn);
-               if (ret) {
-                       kfree(nv_connector);
-                       return ERR_PTR(ret);
-               }
-
+       if (nvif_object_constructed(&nv_connector->conn.object)) {
                ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsHotplug",
                                           nouveau_connector_hotplug,
                                           NVIF_CONN_EVENT_V0_PLUG | NVIF_CONN_EVENT_V0_UNPLUG,
index 35bcb541722b8bb3ea710ff986232cc91121fd60..a2df4918340cb8b4653554bd8e3050782de17763 100644 (file)
@@ -121,7 +121,6 @@ struct nouveau_connector {
        struct drm_connector base;
        enum dcb_connector_type type;
        u8 index;
-       u8 *dcb;
 
        struct nvif_conn conn;
        u64 hpd_pending;
@@ -200,7 +199,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
 }
 
 struct drm_connector *
-nouveau_connector_create(struct drm_device *, const struct dcb_output *);
+nouveau_connector_create(struct drm_device *, int id);
 void nouveau_connector_hpd(struct nouveau_connector *, u64 bits);
 
 extern int nouveau_tv_disable;
index 879569d4ba4cc2918868f1e9ff54eea618205bc4..9ee18cb992644c9506e51d673f7f3fcd996645a2 100644 (file)
@@ -63,5 +63,25 @@ nvif_conn_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_con
        ret = nvif_object_ctor(&disp->object, name ?: "nvifConn", id, NVIF_CLASS_CONN,
                               &args, sizeof(args), &conn->object);
        NVIF_ERRON(ret, &disp->object, "[NEW conn id:%d]", id);
-       return ret;
+       if (ret)
+               return ret;
+
+       conn->id = id;
+
+       switch (args.type) {
+       case NVIF_CONN_V0_VGA      : conn->info.type = NVIF_CONN_VGA; break;
+       case NVIF_CONN_V0_TV       : conn->info.type = NVIF_CONN_TV; break;
+       case NVIF_CONN_V0_DVI_I    : conn->info.type = NVIF_CONN_DVI_I; break;
+       case NVIF_CONN_V0_DVI_D    : conn->info.type = NVIF_CONN_DVI_D; break;
+       case NVIF_CONN_V0_LVDS     : conn->info.type = NVIF_CONN_LVDS; break;
+       case NVIF_CONN_V0_LVDS_SPWG: conn->info.type = NVIF_CONN_LVDS_SPWG; break;
+       case NVIF_CONN_V0_HDMI     : conn->info.type = NVIF_CONN_HDMI; break;
+       case NVIF_CONN_V0_DP       : conn->info.type = NVIF_CONN_DP; break;
+       case NVIF_CONN_V0_EDP      : conn->info.type = NVIF_CONN_EDP; break;
+       default:
+               break;
+       }
+
+       return 0;
+
 }
index 971cccc0892cc0f85e95eca58ed644deeb0c00bd..c6eeb8e44c15fa3bf7db94de97edb7f90af1804e 100644 (file)
@@ -142,6 +142,32 @@ nvkm_uconn_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv
        ret = -EBUSY;
        spin_lock(&disp->client.lock);
        if (!conn->object.func) {
+               switch (conn->info.type) {
+               case DCB_CONNECTOR_VGA      : args->v0.type = NVIF_CONN_V0_VGA; break;
+               case DCB_CONNECTOR_TV_0     :
+               case DCB_CONNECTOR_TV_1     :
+               case DCB_CONNECTOR_TV_3     : args->v0.type = NVIF_CONN_V0_TV; break;
+               case DCB_CONNECTOR_DMS59_0  :
+               case DCB_CONNECTOR_DMS59_1  :
+               case DCB_CONNECTOR_DVI_I    : args->v0.type = NVIF_CONN_V0_DVI_I; break;
+               case DCB_CONNECTOR_DVI_D    : args->v0.type = NVIF_CONN_V0_DVI_D; break;
+               case DCB_CONNECTOR_LVDS     : args->v0.type = NVIF_CONN_V0_LVDS; break;
+               case DCB_CONNECTOR_LVDS_SPWG: args->v0.type = NVIF_CONN_V0_LVDS_SPWG; break;
+               case DCB_CONNECTOR_DMS59_DP0:
+               case DCB_CONNECTOR_DMS59_DP1:
+               case DCB_CONNECTOR_DP       :
+               case DCB_CONNECTOR_mDP      :
+               case DCB_CONNECTOR_USB_C    : args->v0.type = NVIF_CONN_V0_DP; break;
+               case DCB_CONNECTOR_eDP      : args->v0.type = NVIF_CONN_V0_EDP; break;
+               case DCB_CONNECTOR_HDMI_0   :
+               case DCB_CONNECTOR_HDMI_1   :
+               case DCB_CONNECTOR_HDMI_C   : args->v0.type = NVIF_CONN_V0_HDMI; break;
+               default:
+                       WARN_ON(1);
+                       ret = -EINVAL;
+                       break;
+               }
+
                nvkm_object_ctor(&nvkm_uconn, oclass, &conn->object);
                *pobject = &conn->object;
                ret = 0;