drm/amdgpu: properly handle vbios fake edid sizing
authorAlex Deucher <alexander.deucher@amd.com>
Tue, 23 Jul 2024 17:23:56 +0000 (13:23 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 25 Jul 2024 21:41:46 +0000 (17:41 -0400)
The comment in the vbios structure says:
// = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128

This fake edid struct has not been used in a long time, so I'm
not sure if there were actually any boards out there with a non-128 byte
EDID, but align the code with the comment.

Reviewed-by: Thomas Weißschuh <linux@weissschuh.net>
Reported-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://lists.freedesktop.org/archives/amd-gfx/2024-June/109964.html
Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)")
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/atombios_encoders.c

index 25feab188dfe69168f704914589bb65da65445fd..ebf83fee43bb99267c22740a7c0f88a243159c24 100644 (file)
@@ -2065,26 +2065,29 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder)
                                        fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
                                        if (fake_edid_record->ucFakeEDIDLength) {
                                                struct edid *edid;
-                                               int edid_size =
-                                                       max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
-                                               edid = kmalloc(edid_size, GFP_KERNEL);
+                                               int edid_size;
+
+                                               if (fake_edid_record->ucFakeEDIDLength == 128)
+                                                       edid_size = fake_edid_record->ucFakeEDIDLength;
+                                               else
+                                                       edid_size = fake_edid_record->ucFakeEDIDLength * 128;
+                                               edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0],
+                                                              edid_size, GFP_KERNEL);
                                                if (edid) {
-                                                       memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
-                                                              fake_edid_record->ucFakeEDIDLength);
-
                                                        if (drm_edid_is_valid(edid)) {
                                                                adev->mode_info.bios_hardcoded_edid = edid;
                                                                adev->mode_info.bios_hardcoded_edid_size = edid_size;
-                                                       } else
+                                                       } else {
                                                                kfree(edid);
+                                                       }
                                                }
+                                               record += struct_size(fake_edid_record,
+                                                                     ucFakeEDIDString,
+                                                                     edid_size);
+                                       } else {
+                                               /* empty fake edid record must be 3 bytes long */
+                                               record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
                                        }
-                                       record += fake_edid_record->ucFakeEDIDLength ?
-                                                 struct_size(fake_edid_record,
-                                                             ucFakeEDIDString,
-                                                             fake_edid_record->ucFakeEDIDLength) :
-                                                 /* empty fake edid record must be 3 bytes long */
-                                                 sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
                                        break;
                                case LCD_PANEL_RESOLUTION_RECORD_TYPE:
                                        panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;