Skip to content

Commit

Permalink
ACPI: video: Handle fetching EDID that is longer than 256 bytes
Browse files Browse the repository at this point in the history
The ACPI specification allows for an EDID to be up to 512 bytes but
the _DDC EDID fetching code will only try up to 256 bytes.

Modify the code to instead start at 512 bytes and work it's way
down instead.

As _DDC is now called up to 4 times on a machine debugging messages
are noisier than necessary.  Decrease from info to debug.

Link: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/Apx_B_Video_Extensions/output-device-specific-methods.html#ddc-return-the-edid-for-this-device
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
[ rjw: Type mismatch fix, minor whitespace adjustment ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Mario Limonciello authored and Rafael J. Wysocki committed Feb 8, 2024
1 parent 54be6c6 commit 5d389af
Showing 1 changed file with 11 additions and 17 deletions.
28 changes: 11 additions & 17 deletions drivers/acpi/acpi_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,

static int
acpi_video_device_EDID(struct acpi_video_device *device,
union acpi_object **edid, ssize_t length)
union acpi_object **edid, int length)
{
int status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Expand All @@ -625,13 +625,11 @@ acpi_video_device_EDID(struct acpi_video_device *device,

if (!device)
return -ENODEV;
if (length == 128)
arg0.integer.value = 1;
else if (length == 256)
arg0.integer.value = 2;
else
if (!length || (length % 128))
return -EINVAL;

arg0.integer.value = length / 128;

status = acpi_evaluate_object(device->dev->handle, "_DDC", &args, &buffer);
if (ACPI_FAILURE(status))
return -ENODEV;
Expand All @@ -641,7 +639,8 @@ acpi_video_device_EDID(struct acpi_video_device *device,
if (obj && obj->type == ACPI_TYPE_BUFFER)
*edid = obj;
else {
acpi_handle_info(device->dev->handle, "Invalid _DDC data\n");
acpi_handle_debug(device->dev->handle,
"Invalid _DDC data for length %d\n", length);
status = -EFAULT;
kfree(obj);
}
Expand Down Expand Up @@ -1447,7 +1446,6 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,

for (i = 0; i < video->attached_count; i++) {
video_device = video->attached_array[i].bind_info;
length = 256;

if (!video_device)
continue;
Expand Down Expand Up @@ -1478,18 +1476,14 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
continue;
}

status = acpi_video_device_EDID(video_device, &buffer, length);

if (ACPI_FAILURE(status) || !buffer ||
buffer->type != ACPI_TYPE_BUFFER) {
length = 128;
for (length = 512; length > 0; length -= 128) {
status = acpi_video_device_EDID(video_device, &buffer,
length);
if (ACPI_FAILURE(status) || !buffer ||
buffer->type != ACPI_TYPE_BUFFER) {
continue;
}
if (ACPI_SUCCESS(status))
break;
}
if (!length)
continue;

*edid = buffer->buffer.pointer;
return length;
Expand Down

0 comments on commit 5d389af

Please sign in to comment.