diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 118 |
1 files changed, 106 insertions, 12 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a0c93b321482..9865d46f49a8 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <acpi/acpi_bus.h> | 45 | #include <acpi/acpi_bus.h> |
46 | #include <acpi/acpi_drivers.h> | 46 | #include <acpi/acpi_drivers.h> |
47 | #include <linux/suspend.h> | 47 | #include <linux/suspend.h> |
48 | #include <acpi/video.h> | ||
48 | 49 | ||
49 | #define PREFIX "ACPI: " | 50 | #define PREFIX "ACPI: " |
50 | 51 | ||
@@ -65,11 +66,6 @@ | |||
65 | 66 | ||
66 | #define MAX_NAME_LEN 20 | 67 | #define MAX_NAME_LEN 20 |
67 | 68 | ||
68 | #define ACPI_VIDEO_DISPLAY_CRT 1 | ||
69 | #define ACPI_VIDEO_DISPLAY_TV 2 | ||
70 | #define ACPI_VIDEO_DISPLAY_DVI 3 | ||
71 | #define ACPI_VIDEO_DISPLAY_LCD 4 | ||
72 | |||
73 | #define _COMPONENT ACPI_VIDEO_COMPONENT | 69 | #define _COMPONENT ACPI_VIDEO_COMPONENT |
74 | ACPI_MODULE_NAME("video"); | 70 | ACPI_MODULE_NAME("video"); |
75 | 71 | ||
@@ -1007,11 +1003,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
1007 | result = acpi_video_init_brightness(device); | 1003 | result = acpi_video_init_brightness(device); |
1008 | if (result) | 1004 | if (result) |
1009 | return; | 1005 | return; |
1010 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 1006 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); |
1011 | if (!name) | 1007 | if (!name) |
1012 | return; | 1008 | return; |
1009 | count++; | ||
1013 | 1010 | ||
1014 | sprintf(name, "acpi_video%d", count++); | ||
1015 | memset(&props, 0, sizeof(struct backlight_properties)); | 1011 | memset(&props, 0, sizeof(struct backlight_properties)); |
1016 | props.max_brightness = device->brightness->count - 3; | 1012 | props.max_brightness = device->brightness->count - 3; |
1017 | device->backlight = backlight_device_register(name, NULL, device, | 1013 | device->backlight = backlight_device_register(name, NULL, device, |
@@ -1067,10 +1063,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
1067 | if (device->cap._DCS && device->cap._DSS) { | 1063 | if (device->cap._DCS && device->cap._DSS) { |
1068 | static int count; | 1064 | static int count; |
1069 | char *name; | 1065 | char *name; |
1070 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 1066 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); |
1071 | if (!name) | 1067 | if (!name) |
1072 | return; | 1068 | return; |
1073 | sprintf(name, "acpi_video%d", count++); | 1069 | count++; |
1074 | device->output_dev = video_output_register(name, | 1070 | device->output_dev = video_output_register(name, |
1075 | NULL, device, &acpi_output_properties); | 1071 | NULL, device, &acpi_output_properties); |
1076 | kfree(name); | 1072 | kfree(name); |
@@ -1748,11 +1744,27 @@ acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id | |||
1748 | } | 1744 | } |
1749 | 1745 | ||
1750 | static int | 1746 | static int |
1747 | acpi_video_get_device_type(struct acpi_video_bus *video, | ||
1748 | unsigned long device_id) | ||
1749 | { | ||
1750 | struct acpi_video_enumerated_device *ids; | ||
1751 | int i; | ||
1752 | |||
1753 | for (i = 0; i < video->attached_count; i++) { | ||
1754 | ids = &video->attached_array[i]; | ||
1755 | if ((ids->value.int_val & 0xffff) == device_id) | ||
1756 | return ids->value.int_val; | ||
1757 | } | ||
1758 | |||
1759 | return 0; | ||
1760 | } | ||
1761 | |||
1762 | static int | ||
1751 | acpi_video_bus_get_one_device(struct acpi_device *device, | 1763 | acpi_video_bus_get_one_device(struct acpi_device *device, |
1752 | struct acpi_video_bus *video) | 1764 | struct acpi_video_bus *video) |
1753 | { | 1765 | { |
1754 | unsigned long long device_id; | 1766 | unsigned long long device_id; |
1755 | int status; | 1767 | int status, device_type; |
1756 | struct acpi_video_device *data; | 1768 | struct acpi_video_device *data; |
1757 | struct acpi_video_device_attrib* attribute; | 1769 | struct acpi_video_device_attrib* attribute; |
1758 | 1770 | ||
@@ -1797,8 +1809,25 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1797 | } | 1809 | } |
1798 | if(attribute->bios_can_detect) | 1810 | if(attribute->bios_can_detect) |
1799 | data->flags.bios = 1; | 1811 | data->flags.bios = 1; |
1800 | } else | 1812 | } else { |
1801 | data->flags.unknown = 1; | 1813 | /* Check for legacy IDs */ |
1814 | device_type = acpi_video_get_device_type(video, | ||
1815 | device_id); | ||
1816 | /* Ignore bits 16 and 18-20 */ | ||
1817 | switch (device_type & 0xffe2ffff) { | ||
1818 | case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR: | ||
1819 | data->flags.crt = 1; | ||
1820 | break; | ||
1821 | case ACPI_VIDEO_DISPLAY_LEGACY_PANEL: | ||
1822 | data->flags.lcd = 1; | ||
1823 | break; | ||
1824 | case ACPI_VIDEO_DISPLAY_LEGACY_TV: | ||
1825 | data->flags.tvout = 1; | ||
1826 | break; | ||
1827 | default: | ||
1828 | data->flags.unknown = 1; | ||
1829 | } | ||
1830 | } | ||
1802 | 1831 | ||
1803 | acpi_video_device_bind(video, data); | 1832 | acpi_video_device_bind(video, data); |
1804 | acpi_video_device_find_cap(data); | 1833 | acpi_video_device_find_cap(data); |
@@ -2032,6 +2061,71 @@ out: | |||
2032 | return result; | 2061 | return result; |
2033 | } | 2062 | } |
2034 | 2063 | ||
2064 | int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, | ||
2065 | void **edid) | ||
2066 | { | ||
2067 | struct acpi_video_bus *video; | ||
2068 | struct acpi_video_device *video_device; | ||
2069 | union acpi_object *buffer = NULL; | ||
2070 | acpi_status status; | ||
2071 | int i, length; | ||
2072 | |||
2073 | if (!device || !acpi_driver_data(device)) | ||
2074 | return -EINVAL; | ||
2075 | |||
2076 | video = acpi_driver_data(device); | ||
2077 | |||
2078 | for (i = 0; i < video->attached_count; i++) { | ||
2079 | video_device = video->attached_array[i].bind_info; | ||
2080 | length = 256; | ||
2081 | |||
2082 | if (!video_device) | ||
2083 | continue; | ||
2084 | |||
2085 | if (type) { | ||
2086 | switch (type) { | ||
2087 | case ACPI_VIDEO_DISPLAY_CRT: | ||
2088 | if (!video_device->flags.crt) | ||
2089 | continue; | ||
2090 | break; | ||
2091 | case ACPI_VIDEO_DISPLAY_TV: | ||
2092 | if (!video_device->flags.tvout) | ||
2093 | continue; | ||
2094 | break; | ||
2095 | case ACPI_VIDEO_DISPLAY_DVI: | ||
2096 | if (!video_device->flags.dvi) | ||
2097 | continue; | ||
2098 | break; | ||
2099 | case ACPI_VIDEO_DISPLAY_LCD: | ||
2100 | if (!video_device->flags.lcd) | ||
2101 | continue; | ||
2102 | break; | ||
2103 | } | ||
2104 | } else if (video_device->device_id != device_id) { | ||
2105 | continue; | ||
2106 | } | ||
2107 | |||
2108 | status = acpi_video_device_EDID(video_device, &buffer, length); | ||
2109 | |||
2110 | if (ACPI_FAILURE(status) || !buffer || | ||
2111 | buffer->type != ACPI_TYPE_BUFFER) { | ||
2112 | length = 128; | ||
2113 | status = acpi_video_device_EDID(video_device, &buffer, | ||
2114 | length); | ||
2115 | if (ACPI_FAILURE(status) || !buffer || | ||
2116 | buffer->type != ACPI_TYPE_BUFFER) { | ||
2117 | continue; | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | *edid = buffer->buffer.pointer; | ||
2122 | return length; | ||
2123 | } | ||
2124 | |||
2125 | return -ENODEV; | ||
2126 | } | ||
2127 | EXPORT_SYMBOL(acpi_video_get_edid); | ||
2128 | |||
2035 | static int | 2129 | static int |
2036 | acpi_video_bus_get_devices(struct acpi_video_bus *video, | 2130 | acpi_video_bus_get_devices(struct acpi_video_bus *video, |
2037 | struct acpi_device *device) | 2131 | struct acpi_device *device) |