| From 023f5b2d1fdad6ffe33a204a4e76e38edba9d9e5 Mon Sep 17 00:00:00 2001 |
| From: Kyle McMartin <kyle@dreadnought.i.jkkm.org> |
| Date: Thu, 20 May 2010 08:59:58 -0400 |
| Subject: linux-2.6-acpi-video-export-edid.patch |
| |
| |
| drivers/acpi/video.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++---- |
| include/acpi/video.h | 16 +++++++ |
| 2 files changed, 118 insertions(+), 8 deletions(-) |
| |
| diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c |
| index a0c93b3..4b8bda1 100644 |
| |
| |
| @@ -45,6 +45,7 @@ |
| #include <acpi/acpi_bus.h> |
| #include <acpi/acpi_drivers.h> |
| #include <linux/suspend.h> |
| +#include <acpi/video.h> |
| |
| #define PREFIX "ACPI: " |
| |
| @@ -65,11 +66,6 @@ |
| |
| #define MAX_NAME_LEN 20 |
| |
| -#define ACPI_VIDEO_DISPLAY_CRT 1 |
| -#define ACPI_VIDEO_DISPLAY_TV 2 |
| -#define ACPI_VIDEO_DISPLAY_DVI 3 |
| -#define ACPI_VIDEO_DISPLAY_LCD 4 |
| - |
| #define _COMPONENT ACPI_VIDEO_COMPONENT |
| ACPI_MODULE_NAME("video"); |
| |
| @@ -1748,11 +1744,27 @@ acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id |
| } |
| |
| static int |
| +acpi_video_get_device_type(struct acpi_video_bus *video, |
| + unsigned long device_id) |
| +{ |
| + struct acpi_video_enumerated_device *ids; |
| + int i; |
| + |
| + for (i = 0; i < video->attached_count; i++) { |
| + ids = &video->attached_array[i]; |
| + if ((ids->value.int_val & 0xffff) == device_id) |
| + return ids->value.int_val; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +static int |
| acpi_video_bus_get_one_device(struct acpi_device *device, |
| struct acpi_video_bus *video) |
| { |
| unsigned long long device_id; |
| - int status; |
| + int status, device_type; |
| struct acpi_video_device *data; |
| struct acpi_video_device_attrib* attribute; |
| |
| @@ -1797,8 +1809,25 @@ acpi_video_bus_get_one_device(struct acpi_device *device, |
| } |
| if(attribute->bios_can_detect) |
| data->flags.bios = 1; |
| - } else |
| - data->flags.unknown = 1; |
| + } else { |
| + /* Check for legacy IDs */ |
| + device_type = acpi_video_get_device_type(video, |
| + device_id); |
| + /* Ignore bits 16 and 18-20 */ |
| + switch (device_type & 0xffe2ffff) { |
| + case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR: |
| + data->flags.crt = 1; |
| + break; |
| + case ACPI_VIDEO_DISPLAY_LEGACY_PANEL: |
| + data->flags.lcd = 1; |
| + break; |
| + case ACPI_VIDEO_DISPLAY_LEGACY_TV: |
| + data->flags.tvout = 1; |
| + break; |
| + default: |
| + data->flags.unknown = 1; |
| + } |
| + } |
| |
| acpi_video_device_bind(video, data); |
| acpi_video_device_find_cap(data); |
| @@ -2032,6 +2061,71 @@ out: |
| return result; |
| } |
| |
| +int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, |
| + void **edid) |
| +{ |
| + struct acpi_video_bus *video; |
| + struct acpi_video_device *video_device; |
| + union acpi_object *buffer = NULL; |
| + acpi_status status; |
| + int i, length; |
| + |
| + if (!device || !acpi_driver_data(device)) |
| + return -EINVAL; |
| + |
| + video = acpi_driver_data(device); |
| + |
| + for (i = 0; i < video->attached_count; i++) { |
| + video_device = video->attached_array[i].bind_info; |
| + length = 256; |
| + |
| + if (!video_device) |
| + continue; |
| + |
| + if (type) { |
| + switch (type) { |
| + case ACPI_VIDEO_DISPLAY_CRT: |
| + if (!video_device->flags.crt) |
| + continue; |
| + break; |
| + case ACPI_VIDEO_DISPLAY_TV: |
| + if (!video_device->flags.tvout) |
| + continue; |
| + break; |
| + case ACPI_VIDEO_DISPLAY_DVI: |
| + if (!video_device->flags.dvi) |
| + continue; |
| + break; |
| + case ACPI_VIDEO_DISPLAY_LCD: |
| + if (!video_device->flags.lcd) |
| + continue; |
| + break; |
| + } |
| + } else if (video_device->device_id != device_id) { |
| + continue; |
| + } |
| + |
| + status = acpi_video_device_EDID(video_device, &buffer, length); |
| + |
| + if (ACPI_FAILURE(status) || !buffer || |
| + buffer->type != ACPI_TYPE_BUFFER) { |
| + length = 128; |
| + status = acpi_video_device_EDID(video_device, &buffer, |
| + length); |
| + if (ACPI_FAILURE(status) || !buffer || |
| + buffer->type != ACPI_TYPE_BUFFER) { |
| + continue; |
| + } |
| + } |
| + |
| + *edid = buffer->buffer.pointer; |
| + return length; |
| + } |
| + |
| + return -ENODEV; |
| +} |
| +EXPORT_SYMBOL(acpi_video_get_edid); |
| + |
| static int |
| acpi_video_bus_get_devices(struct acpi_video_bus *video, |
| struct acpi_device *device) |
| diff --git a/include/acpi/video.h b/include/acpi/video.h |
| index cf7be3d..551793c 100644 |
| |
| |
| @@ -1,12 +1,28 @@ |
| #ifndef __ACPI_VIDEO_H |
| #define __ACPI_VIDEO_H |
| |
| +#define ACPI_VIDEO_DISPLAY_CRT 1 |
| +#define ACPI_VIDEO_DISPLAY_TV 2 |
| +#define ACPI_VIDEO_DISPLAY_DVI 3 |
| +#define ACPI_VIDEO_DISPLAY_LCD 4 |
| + |
| +#define ACPI_VIDEO_DISPLAY_LEGACY_MONITOR 0x0100 |
| +#define ACPI_VIDEO_DISPLAY_LEGACY_PANEL 0x0110 |
| +#define ACPI_VIDEO_DISPLAY_LEGACY_TV 0x0200 |
| + |
| #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) |
| extern int acpi_video_register(void); |
| extern void acpi_video_unregister(void); |
| +extern int acpi_video_get_edid(struct acpi_device *device, int type, |
| + int device_id, void **edid); |
| #else |
| static inline int acpi_video_register(void) { return 0; } |
| static inline void acpi_video_unregister(void) { return; } |
| +static inline int acpi_video_get_edid(struct acpi_device *device, int type, |
| + int device_id, void **edid) |
| +{ |
| + return -ENODEV; |
| +} |
| #endif |
| |
| #endif |
| -- |
| 1.7.0.1 |
| |