Line 0
Link Here
|
0 |
- |
1 |
/* |
|
|
2 |
* video_detect.c: |
3 |
* Provides acpi_is_video_device() for early scanning of ACPI devices in scan.c |
4 |
* There a Linux specific (Spec does not provide a HID for video devices) is |
5 |
* assinged |
6 |
* |
7 |
* After PCI devices are glued with ACPI devices |
8 |
* acpi_get_physical_pci_device() can be called to identify ACPI graphics |
9 |
* devices for which a real graphics card is plugged in |
10 |
* |
11 |
* Now acpi_video_get_capabilities() can be called to check which |
12 |
* capabilities the graphics cards plugged in support. |
13 |
* |
14 |
* Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B) |
15 |
* are available, video.ko should be used to handle the device. |
16 |
* |
17 |
* Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi, |
18 |
* sony_acpi,... can take care about backlight brightness and display output |
19 |
* switching. |
20 |
* |
21 |
* Copyright 2008 Thomas Renninger <trenn@suse.de> |
22 |
*/ |
23 |
|
24 |
/* If video.ko is not selected, we do not need to protect vendor acpi drivers */ |
25 |
#if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) |
26 |
|
27 |
#include <linux/acpi.h> |
28 |
|
29 |
ACPI_MODULE_NAME("video"); |
30 |
#define ACPI_VIDEO_COMPONENT 0x08000000 |
31 |
#define _COMPONENT ACPI_VIDEO_COMPONENT |
32 |
|
33 |
/* video/backlight support */ |
34 |
#define ACPI_VIDEO_OUTPUT_SWITCHING 1 |
35 |
#define ACPI_VIDEO_DEVICE_POSTING 2 |
36 |
#define ACPI_VIDEO_ROM_AVAILABLE 4 |
37 |
#define ACPI_VIDEO_BACKLIGHT 8 |
38 |
#define ACPI_VIDEO_IGD 16 |
39 |
#define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR 32 |
40 |
#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR 64 |
41 |
|
42 |
long acpi_video_support; |
43 |
EXPORT_SYMBOL(acpi_video_support); |
44 |
|
45 |
static __devinit acpi_status |
46 |
acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, |
47 |
void **retyurn_value) |
48 |
{ |
49 |
long *cap = context; |
50 |
acpi_handle h_dummy; |
51 |
|
52 |
if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) && |
53 |
ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) { |
54 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " |
55 |
"support\n")); |
56 |
*cap |= ACPI_VIDEO_BACKLIGHT; |
57 |
return 0; |
58 |
} |
59 |
return -ENODEV; |
60 |
} |
61 |
|
62 |
/* Returns true if the device is a video device which can be handled by |
63 |
* video.ko. |
64 |
* The device will get a Linux specific CID added in scan.c to |
65 |
* identify the device as an ACPI graphics device |
66 |
* Be aware that the graphics device may not be physically present |
67 |
* Use acpi_video_get_capabilities() to detect general ACPI video |
68 |
* capabilities of present cards |
69 |
*/ |
70 |
long acpi_is_video_device(struct acpi_device *device) |
71 |
{ |
72 |
acpi_handle h_dummy; |
73 |
long video_caps = 0; |
74 |
|
75 |
if (!device) |
76 |
return 0; |
77 |
|
78 |
/* Since there is no HID, CID for ACPI Video drivers, we have |
79 |
* to check well known required nodes for each feature we support. |
80 |
*/ |
81 |
|
82 |
/* Does this device able to support video switching ? */ |
83 |
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && |
84 |
ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) |
85 |
video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; |
86 |
|
87 |
/* Does this device able to retrieve a video ROM ? */ |
88 |
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) |
89 |
video_caps |= ACPI_VIDEO_ROM_AVAILABLE; |
90 |
|
91 |
/* Does this device able to configure which video head to be POSTed ? */ |
92 |
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && |
93 |
ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && |
94 |
ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) |
95 |
video_caps |= ACPI_VIDEO_DEVICE_POSTING; |
96 |
|
97 |
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "DRDY", &h_dummy))) { |
98 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IGD device\n")); |
99 |
video_caps |= ACPI_VIDEO_IGD; |
100 |
} |
101 |
|
102 |
acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle, ACPI_UINT32_MAX, |
103 |
acpi_backlight_cap_match, &video_caps, NULL); |
104 |
|
105 |
return video_caps; |
106 |
} |
107 |
EXPORT_SYMBOL(acpi_is_video_device); |
108 |
|
109 |
static __devinit acpi_status |
110 |
find_video(acpi_handle handle, u32 lvl, void *context, void **rv) |
111 |
{ |
112 |
long *cap = context; |
113 |
struct device *dev; |
114 |
struct acpi_device *acpi_dev; |
115 |
|
116 |
const struct acpi_device_id video_ids[] = { |
117 |
{ACPI_VIDEO_HID, 0}, |
118 |
{"", 0}, |
119 |
}; |
120 |
acpi_bus_get_device(handle, &acpi_dev); |
121 |
|
122 |
if (!acpi_match_device_ids(acpi_dev, video_ids)) { |
123 |
dev = acpi_get_physical_pci_device(handle); |
124 |
if (!dev) |
125 |
return AE_OK; |
126 |
put_device(dev); |
127 |
*cap |= acpi_is_video_device(acpi_dev); |
128 |
printk("We have 0x%lX vid support\n", *cap); |
129 |
} |
130 |
return AE_OK; |
131 |
} |
132 |
|
133 |
long __devinit acpi_video_get_capabilities(void) |
134 |
{ |
135 |
long video_caps = 0; |
136 |
|
137 |
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
138 |
ACPI_UINT32_MAX, find_video, &video_caps, NULL); |
139 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support\n", |
140 |
video_caps)); |
141 |
return video_caps; |
142 |
} |
143 |
|
144 |
/* Returns true if video.ko can do backlight switching |
145 |
* |
146 |
* ToDo: Remove the IGD check as soon as there is a working driver |
147 |
* for it available |
148 |
*/ |
149 |
int acpi_video_backlight_support(void) |
150 |
{ |
151 |
|
152 |
if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR) |
153 |
return 0; |
154 |
|
155 |
return (acpi_video_support & ACPI_VIDEO_BACKLIGHT) && |
156 |
!(acpi_video_support & ACPI_VIDEO_IGD); |
157 |
} |
158 |
EXPORT_SYMBOL(acpi_video_backlight_support); |
159 |
|
160 |
/* Returns true if video.ko can do display output switching. |
161 |
* This does not work well/at all with binary graphics drivers |
162 |
* which disable system io ranges and do it on their own. |
163 |
* |
164 |
* It should work well when we have an IGD driver for Intel |
165 |
* graphics cards. |
166 |
*/ |
167 |
int acpi_video_display_switch_support(void) |
168 |
{ |
169 |
|
170 |
if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR) |
171 |
return 0; |
172 |
return (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING) && |
173 |
!(acpi_video_support & ACPI_VIDEO_IGD); |
174 |
} |
175 |
EXPORT_SYMBOL(acpi_video_display_switch_support); |
176 |
|
177 |
/* Use acpi_video_vendor=backlight,display_output |
178 |
* To force that backlight or display output switching is processed by vendor |
179 |
* specific acpi drivers instead of the ACPI video.ko driver |
180 |
*/ |
181 |
int __init acpi_vendor(char *str) |
182 |
{ |
183 |
if (str == NULL || *str == '\0') |
184 |
return 1; |
185 |
else { |
186 |
if (!strcmp("backlight", str)) |
187 |
acpi_video_support &= |
188 |
ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; |
189 |
if (!strcmp("display_output", str)) |
190 |
acpi_video_support &= |
191 |
ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR; |
192 |
} |
193 |
return 1; |
194 |
} |
195 |
__setup("acpi_vendor=", acpi_vendor); |
196 |
|
197 |
#else |
198 |
|
199 |
long acpi_video_get_capabilities(void) |
200 |
{ |
201 |
return 0; |
202 |
} |
203 |
EXPORT_SYMBOL(acpi_video_get_capabilities); |
204 |
|
205 |
long acpi_is_video_device(struct acpi_device *device) |
206 |
{ |
207 |
return 0; |
208 |
} |
209 |
EXPORT_SYMBOL(acpi_is_video_device); |
210 |
|
211 |
int acpi_video_backlight_support(void) |
212 |
{ |
213 |
return 0; |
214 |
} |
215 |
EXPORT_SYMBOL(acpi_video_backlight_support); |
216 |
|
217 |
int acpi_video_display_switch_support() |
218 |
{ |
219 |
return 0; |
220 |
} |
221 |
EXPORT_SYMBOL(acpi_video_display_switch_support); |
222 |
|
223 |
#endif /* defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) */ |