]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/nouveau/disp: add output method to fetch edid
authorBen Skeggs <bskeggs@redhat.com>
Tue, 19 Sep 2023 21:56:03 +0000 (17:56 -0400)
committerLyude Paul <lyude@redhat.com>
Tue, 19 Sep 2023 22:21:54 +0000 (18:21 -0400)
- needed to support TMDS EDID on 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-9-lyude@redhat.com
drivers/gpu/drm/nouveau/include/nvif/if0012.h
drivers/gpu/drm/nouveau/include/nvif/outp.h
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nvif/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c

index 923bc30af2a9244cd55baa6097bc13877eb68536..725d6e8e3d2d398300e0d4b388a31a3ff1e203ab 100644 (file)
@@ -13,6 +13,7 @@ union nvif_outp_args {
 };
 
 #define NVIF_OUTP_V0_DETECT        0x00
+#define NVIF_OUTP_V0_EDID_GET      0x01
 
 #define NVIF_OUTP_V0_ACQUIRE       0x11
 #define NVIF_OUTP_V0_RELEASE       0x12
@@ -36,6 +37,15 @@ union nvif_outp_detect_args {
        } v0;
 };
 
+union nvif_outp_edid_get_args {
+       struct nvif_outp_edid_get_v0 {
+               __u8  version;
+               __u8  pad01;
+               __u16 size;
+               __u8  data[2048];
+       } v0;
+};
+
 union nvif_outp_load_detect_args {
        struct nvif_outp_load_detect_v0 {
                __u8  version;
index c3e1e4d2f1a11a31af1927264898cba39840bb9f..7c2c34a84fbd882693018c4b17a2919b267095ef 100644 (file)
@@ -25,6 +25,7 @@ enum nvif_outp_detect_status {
 };
 
 enum nvif_outp_detect_status nvif_outp_detect(struct nvif_outp *);
+int nvif_outp_edid_get(struct nvif_outp *, u8 **pedid);
 
 int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
 int nvif_outp_acquire_rgb_crt(struct nvif_outp *);
index a290a2844547ca884a9f802df3cc05c7295d0636..c079686fa2408f54bdb13e93dfc24640d0f25a8d 100644 (file)
@@ -570,7 +570,6 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_encoder *nv_encoder = NULL;
        struct nouveau_encoder *nv_partner;
-       struct i2c_adapter *i2c;
        int type;
        int ret;
        enum drm_connector_status conn_status = connector_status_disconnected;
@@ -593,15 +592,20 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
        }
 
        nv_encoder = nouveau_connector_ddc_detect(connector);
-       if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {
-               struct edid *new_edid;
+       if (nv_encoder) {
+               struct edid *new_edid = NULL;
 
-               if ((vga_switcheroo_handler_flags() &
-                    VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
-                   nv_connector->type == DCB_CONNECTOR_LVDS)
-                       new_edid = drm_get_edid_switcheroo(connector, i2c);
-               else
-                       new_edid = drm_get_edid(connector, i2c);
+               if (nv_encoder->i2c) {
+                       if ((vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
+                           nv_connector->type == DCB_CONNECTOR_LVDS)
+                               new_edid = drm_get_edid_switcheroo(connector, nv_encoder->i2c);
+                       else
+                               new_edid = drm_get_edid(connector, nv_encoder->i2c);
+               } else {
+                       ret = nvif_outp_edid_get(&nv_encoder->outp, (u8 **)&new_edid);
+                       if (ret < 0)
+                               return connector_status_disconnected;
+               }
 
                nouveau_connector_set_edid(nv_connector, new_edid);
                if (!nv_connector->edid) {
index 7f1daab35a0d22ad27528f325c228694c3ed0c2d..10480142eea5a8b0537c0e61200edf7378322775 100644 (file)
@@ -210,6 +210,36 @@ nvif_outp_load_detect(struct nvif_outp *outp, u32 loadval)
        return ret < 0 ? ret : args.load;
 }
 
+int
+nvif_outp_edid_get(struct nvif_outp *outp, u8 **pedid)
+{
+       struct nvif_outp_edid_get_v0 *args;
+       int ret;
+
+       args = kmalloc(sizeof(*args), GFP_KERNEL);
+       if (!args)
+               return -ENOMEM;
+
+       args->version = 0;
+
+       ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_EDID_GET, args, sizeof(*args));
+       NVIF_ERRON(ret, &outp->object, "[EDID_GET] size:%d", args->size);
+       if (ret)
+               goto done;
+
+       *pedid = kmalloc(args->size, GFP_KERNEL);
+       if (!*pedid) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       memcpy(*pedid, args->data, args->size);
+       ret = args->size;
+done:
+       kfree(args);
+       return ret;
+}
+
 enum nvif_outp_detect_status
 nvif_outp_detect(struct nvif_outp *outp)
 {
index 8c9fe878f320932b1ee5f89d6fc6a3250b870492..1cd70868f2255f34bd6449bf7ed0d4d491c979e1 100644 (file)
@@ -87,6 +87,7 @@ struct nvkm_outp_func {
        void (*fini)(struct nvkm_outp *);
 
        int (*detect)(struct nvkm_outp *);
+       int (*edid_get)(struct nvkm_outp *, u8 *data, u16 *size);
 
        int (*acquire)(struct nvkm_outp *);
        void (*release)(struct nvkm_outp *);
index 43752e216ce88a88d2534bdc93bab9a8b986fd2a..0c4ffa3ffb2880f4690a38e4e4548b21a47afa37 100644 (file)
@@ -275,6 +275,20 @@ nvkm_uoutp_mthd_load_detect(struct nvkm_outp *outp, void *argv, u32 argc)
        return ret;
 }
 
+static int
+nvkm_uoutp_mthd_edid_get(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+       union nvif_outp_edid_get_args *args = argv;
+
+       if (argc != sizeof(args->v0) || args->v0.version != 0)
+               return -ENOSYS;
+       if (!outp->func->edid_get)
+               return -EINVAL;
+
+       args->v0.size = ARRAY_SIZE(args->v0.data);
+       return outp->func->edid_get(outp, args->v0.data, &args->v0.size);
+}
+
 static int
 nvkm_uoutp_mthd_detect(struct nvkm_outp *outp, void *argv, u32 argc)
 {
@@ -319,6 +333,7 @@ nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc
 {
        switch (mthd) {
        case NVIF_OUTP_V0_DETECT     : return nvkm_uoutp_mthd_detect     (outp, argv, argc);
+       case NVIF_OUTP_V0_EDID_GET   : return nvkm_uoutp_mthd_edid_get   (outp, argv, argc);
        case NVIF_OUTP_V0_ACQUIRE    : return nvkm_uoutp_mthd_acquire    (outp, argv, argc);
        case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, argv, argc);
        case NVIF_OUTP_V0_DP_AUX_PWR : return nvkm_uoutp_mthd_dp_aux_pwr (outp, argv, argc);