]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.arch/0001-Check-for-ACPI-backlight-support.patch
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / 0001-Check-for-ACPI-backlight-support.patch
1 From: Thomas Renninger <trenn@suse.de>
2 Subject: [PATCH] Check for ACPI backlight support otherwise use vendor ACPI drivers
3 Patch-Mainline: queued for .28 in Len's/ak's ACPI tree
4
5 commit f43d728731c691772ddc29e50d25c68a859935b5
6
7 If an ACPI graphics device supports backlight brightness functions (cmp. with
8 latest ACPI spec Appendix B), let the ACPI video driver control backlight and
9 switch backlight control off in vendor specific ACPI drivers (asus_acpi,
10 thinkpad_acpi, eeepc, fujitsu_laptop, msi_laptop, sony_laptop, acer-wmi).
11
12 Currently it is possible to load above drivers and let both poke on the
13 brightness HW registers, the video and vendor specific ACPI drivers -> bad.
14
15 This patch provides the basic support to check for BIOS capabilities before
16 driver loading time. Driver specific modifications are in separate follow up
17 patches.
18
19 acpi_backlight=vendor/video
20 boot params forces video.ko or vendor specific drivers to keep its
21 fingers off backlight control even it would find needed functions.
22 The corresponding vendor specific driver be used then.
23
24 Signed-off-by: Thomas Renninger <trenn@suse.de>
25 Signed-off-by: Andi Kleen <ak@linux.intel.com>
26 ---
27 Documentation/kernel-parameters.txt | 13 +
28 drivers/acpi/Makefile | 5
29 drivers/acpi/scan.c | 32 ----
30 drivers/acpi/video.c | 28 ++-
31 drivers/acpi/video_detect.c | 268 ++++++++++++++++++++++++++++++++++++
32 include/linux/acpi.h | 44 +++++
33 6 files changed, 347 insertions(+), 43 deletions(-)
34 create mode 100644 drivers/acpi/video_detect.c
35
36 --- a/Documentation/kernel-parameters.txt
37 +++ b/Documentation/kernel-parameters.txt
38 @@ -200,6 +200,19 @@ and is between 256 and 4096 characters.
39 that require a timer override, but don't have
40 HPET
41
42 + acpi_backlight= [HW,ACPI]
43 + acpi_backlight=vendor
44 + acpi_backlight=video
45 + If set to vendor, it enforces the use of a
46 + vendor specific ACPI driver for backlight switching
47 + (e.g. thinkpad_acpi, sony_acpi, etc.) instead
48 + of the video.ko driver.
49 +
50 + acpi_display_output= [HW,ACPI]
51 + acpi_display_output=vendor
52 + acpi_display_output=video
53 + See above.
54 +
55 acpi.debug_layer= [HW,ACPI]
56 Format: <int>
57 Each bit of the <int> indicates an ACPI debug layer,
58 --- a/drivers/acpi/Makefile
59 +++ b/drivers/acpi/Makefile
60 @@ -46,7 +46,12 @@ obj-$(CONFIG_ACPI_BUTTON) += button.o
61 obj-$(CONFIG_ACPI_FAN) += fan.o
62 obj-$(CONFIG_ACPI_DOCK) += dock.o
63 obj-$(CONFIG_ACPI_BAY) += bay.o
64 +
65 obj-$(CONFIG_ACPI_VIDEO) += video.o
66 +ifdef CONFIG_ACPI_VIDEO
67 +obj-y += video_detect.o
68 +endif
69 +
70 obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
71 obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
72 obj-$(CONFIG_ACPI_POWER) += power.o
73 --- a/drivers/acpi/scan.c
74 +++ b/drivers/acpi/scan.c
75 @@ -908,36 +908,6 @@ static void acpi_device_get_busid(struct
76 }
77 }
78
79 -static int
80 -acpi_video_bus_match(struct acpi_device *device)
81 -{
82 - acpi_handle h_dummy;
83 -
84 - if (!device)
85 - return -EINVAL;
86 -
87 - /* Since there is no HID, CID for ACPI Video drivers, we have
88 - * to check well known required nodes for each feature we support.
89 - */
90 -
91 - /* Does this device able to support video switching ? */
92 - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) &&
93 - ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
94 - return 0;
95 -
96 - /* Does this device able to retrieve a video ROM ? */
97 - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy)))
98 - return 0;
99 -
100 - /* Does this device able to configure which video head to be POSTed ? */
101 - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) &&
102 - ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) &&
103 - ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy)))
104 - return 0;
105 -
106 - return -ENODEV;
107 -}
108 -
109 /*
110 * acpi_bay_match - see if a device is an ejectable driver bay
111 *
112 @@ -1020,7 +990,7 @@ static void acpi_device_set_id(struct ac
113 will get autoloaded and the device might still match
114 against another driver.
115 */
116 - if (ACPI_SUCCESS(acpi_video_bus_match(device)))
117 + if (acpi_is_video_device(device))
118 cid_add = ACPI_VIDEO_HID;
119 else if (ACPI_SUCCESS(acpi_bay_match(device)))
120 cid_add = ACPI_BAY_HID;
121 --- a/drivers/acpi/video.c
122 +++ b/drivers/acpi/video.c
123 @@ -759,7 +759,8 @@ static void acpi_video_device_find_cap(s
124 device->cap._DSS = 1;
125 }
126
127 - max_level = acpi_video_init_brightness(device);
128 + if (acpi_video_backlight_support())
129 + max_level = acpi_video_init_brightness(device);
130
131 if (device->cap._BCL && device->cap._BCM && max_level > 0) {
132 int result;
133 @@ -805,18 +806,21 @@ static void acpi_video_device_find_cap(s
134 printk(KERN_ERR PREFIX "Create sysfs link\n");
135
136 }
137 - if (device->cap._DCS && device->cap._DSS){
138 - static int count = 0;
139 - char *name;
140 - name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
141 - if (!name)
142 - return;
143 - sprintf(name, "acpi_video%d", count++);
144 - device->output_dev = video_output_register(name,
145 - NULL, device, &acpi_output_properties);
146 - kfree(name);
147 +
148 + if (acpi_video_display_switch_support()) {
149 +
150 + if (device->cap._DCS && device->cap._DSS) {
151 + static int count;
152 + char *name;
153 + name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
154 + if (!name)
155 + return;
156 + sprintf(name, "acpi_video%d", count++);
157 + device->output_dev = video_output_register(name,
158 + NULL, device, &acpi_output_properties);
159 + kfree(name);
160 + }
161 }
162 - return;
163 }
164
165 /*
166 --- /dev/null
167 +++ b/drivers/acpi/video_detect.c
168 @@ -0,0 +1,268 @@
169 +/*
170 + * Copyright (C) 2008 SuSE Linux Products GmbH
171 + * Thomas Renninger <trenn@suse.de>
172 + *
173 + * May be copied or modified under the terms of the GNU General Public License
174 + *
175 + * video_detect.c:
176 + * Provides acpi_is_video_device() for early scanning of ACPI devices in scan.c
177 + * There a Linux specific (Spec does not provide a HID for video devices) is
178 + * assinged
179 + *
180 + * After PCI devices are glued with ACPI devices
181 + * acpi_get_physical_pci_device() can be called to identify ACPI graphics
182 + * devices for which a real graphics card is plugged in
183 + *
184 + * Now acpi_video_get_capabilities() can be called to check which
185 + * capabilities the graphics cards plugged in support. The check for general
186 + * video capabilities will be triggered by the first caller of
187 + * acpi_video_get_capabilities(NULL); which will happen when the first
188 + * backlight (or display output) switching supporting driver calls:
189 + * acpi_video_backlight_support();
190 + *
191 + * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B)
192 + * are available, video.ko should be used to handle the device.
193 + *
194 + * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi,
195 + * sony_acpi,... can take care about backlight brightness and display output
196 + * switching.
197 + *
198 + * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)
199 + * this file will not be compiled, acpi_video_get_capabilities() and
200 + * acpi_video_backlight_support() will always return 0 and vendor specific
201 + * drivers always can handle backlight.
202 + *
203 + */
204 +
205 +#include <linux/acpi.h>
206 +#include <linux/dmi.h>
207 +
208 +ACPI_MODULE_NAME("video");
209 +#define ACPI_VIDEO_COMPONENT 0x08000000
210 +#define _COMPONENT ACPI_VIDEO_COMPONENT
211 +
212 +static long acpi_video_support;
213 +static bool acpi_video_caps_checked;
214 +
215 +static acpi_status
216 +acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
217 + void **retyurn_value)
218 +{
219 + long *cap = context;
220 + acpi_handle h_dummy;
221 +
222 + if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) &&
223 + ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) {
224 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
225 + "support\n"));
226 + *cap |= ACPI_VIDEO_BACKLIGHT;
227 + /* We have backlight support, no need to scan further */
228 + return AE_CTRL_TERMINATE;
229 + }
230 + return 0;
231 +}
232 +
233 +/* Returns true if the device is a video device which can be handled by
234 + * video.ko.
235 + * The device will get a Linux specific CID added in scan.c to
236 + * identify the device as an ACPI graphics device
237 + * Be aware that the graphics device may not be physically present
238 + * Use acpi_video_get_capabilities() to detect general ACPI video
239 + * capabilities of present cards
240 + */
241 +long acpi_is_video_device(struct acpi_device *device)
242 +{
243 + acpi_handle h_dummy;
244 + long video_caps = 0;
245 +
246 + if (!device)
247 + return 0;
248 +
249 + /* Does this device able to support video switching ? */
250 + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) &&
251 + ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
252 + video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
253 +
254 + /* Does this device able to retrieve a video ROM ? */
255 + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy)))
256 + video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
257 +
258 + /* Does this device able to configure which video head to be POSTed ? */
259 + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) &&
260 + ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) &&
261 + ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy)))
262 + video_caps |= ACPI_VIDEO_DEVICE_POSTING;
263 +
264 + /* Only check for backlight functionality if one of the above hit. */
265 + if (video_caps)
266 + acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle,
267 + ACPI_UINT32_MAX, acpi_backlight_cap_match,
268 + &video_caps, NULL);
269 +
270 + return video_caps;
271 +}
272 +EXPORT_SYMBOL(acpi_is_video_device);
273 +
274 +static acpi_status
275 +find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
276 +{
277 + long *cap = context;
278 + struct device *dev;
279 + struct acpi_device *acpi_dev;
280 +
281 + const struct acpi_device_id video_ids[] = {
282 + {ACPI_VIDEO_HID, 0},
283 + {"", 0},
284 + };
285 + if (acpi_bus_get_device(handle, &acpi_dev))
286 + return AE_OK;
287 +
288 + if (!acpi_match_device_ids(acpi_dev, video_ids)) {
289 + dev = acpi_get_physical_pci_device(handle);
290 + if (!dev)
291 + return AE_OK;
292 + put_device(dev);
293 + *cap |= acpi_is_video_device(acpi_dev);
294 + }
295 + return AE_OK;
296 +}
297 +
298 +/*
299 + * Returns the video capabilities of a specific ACPI graphics device
300 + *
301 + * if NULL is passed as argument all ACPI devices are enumerated and
302 + * all graphics capabilities of physically present devices are
303 + * summerized and returned. This is cached and done only once.
304 + */
305 +long acpi_video_get_capabilities(acpi_handle graphics_handle)
306 +{
307 + long caps = 0;
308 + struct acpi_device *tmp_dev;
309 + acpi_status status;
310 +
311 + if (acpi_video_caps_checked && graphics_handle == NULL)
312 + return acpi_video_support;
313 +
314 + if (!graphics_handle) {
315 + /* Only do the global walk through all graphics devices once */
316 + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
317 + ACPI_UINT32_MAX, find_video,
318 + &caps, NULL);
319 + /* There might be boot param flags set already... */
320 + acpi_video_support |= caps;
321 + acpi_video_caps_checked = 1;
322 + /* Add blacklists here. Be careful to use the right *DMI* bits
323 + * to still be able to override logic via boot params, e.g.:
324 + *
325 + * if (dmi_name_in_vendors("XY")) {
326 + * acpi_video_support |=
327 + * ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR;
328 + * acpi_video_support |=
329 + * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
330 + *}
331 + */
332 + } else {
333 + status = acpi_bus_get_device(graphics_handle, &tmp_dev);
334 + if (ACPI_FAILURE(status)) {
335 + ACPI_EXCEPTION((AE_INFO, status, "Invalid device"));
336 + return 0;
337 + }
338 + acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle,
339 + ACPI_UINT32_MAX, find_video,
340 + &caps, NULL);
341 + }
342 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n",
343 + graphics_handle ? caps : acpi_video_support,
344 + graphics_handle ? "on device " : "in general",
345 + graphics_handle ? acpi_device_bid(tmp_dev) : ""));
346 + return caps;
347 +}
348 +EXPORT_SYMBOL(acpi_video_get_capabilities);
349 +
350 +/* Returns true if video.ko can do backlight switching */
351 +int acpi_video_backlight_support(void)
352 +{
353 + /*
354 + * We must check whether the ACPI graphics device is physically plugged
355 + * in. Therefore this must be called after binding PCI and ACPI devices
356 + */
357 + if (!acpi_video_caps_checked)
358 + acpi_video_get_capabilities(NULL);
359 +
360 + /* First check for boot param -> highest prio */
361 + if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR)
362 + return 0;
363 + else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO)
364 + return 1;
365 +
366 + /* Then check for DMI blacklist -> second highest prio */
367 + if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VENDOR)
368 + return 0;
369 + else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VIDEO)
370 + return 1;
371 +
372 + /* Then go the default way */
373 + return acpi_video_support & ACPI_VIDEO_BACKLIGHT;
374 +}
375 +EXPORT_SYMBOL(acpi_video_backlight_support);
376 +
377 +/*
378 + * Returns true if video.ko can do display output switching.
379 + * This does not work well/at all with binary graphics drivers
380 + * which disable system io ranges and do it on their own.
381 + */
382 +int acpi_video_display_switch_support(void)
383 +{
384 + if (!acpi_video_caps_checked)
385 + acpi_video_get_capabilities(NULL);
386 +
387 + if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR)
388 + return 0;
389 + else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO)
390 + return 1;
391 +
392 + if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR)
393 + return 0;
394 + else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO)
395 + return 1;
396 +
397 + return acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING;
398 +}
399 +EXPORT_SYMBOL(acpi_video_display_switch_support);
400 +
401 +/*
402 + * Use acpi_display_output=vendor/video or acpi_backlight=vendor/video
403 + * To force that backlight or display output switching is processed by vendor
404 + * specific acpi drivers or video.ko driver.
405 + */
406 +int __init acpi_backlight(char *str)
407 +{
408 + if (str == NULL || *str == '\0')
409 + return 1;
410 + else {
411 + if (!strcmp("vendor", str))
412 + acpi_video_support |=
413 + ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR;
414 + if (!strcmp("video", str))
415 + acpi_video_support |=
416 + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO;
417 + }
418 + return 1;
419 +}
420 +__setup("acpi_backlight=", acpi_backlight);
421 +
422 +int __init acpi_display_output(char *str)
423 +{
424 + if (str == NULL || *str == '\0')
425 + return 1;
426 + else {
427 + if (!strcmp("vendor", str))
428 + acpi_video_support |=
429 + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR;
430 + if (!strcmp("video", str))
431 + acpi_video_support |=
432 + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO;
433 + }
434 + return 1;
435 +}
436 +__setup("acpi_display_output=", acpi_display_output);
437 --- a/include/linux/acpi.h
438 +++ b/include/linux/acpi.h
439 @@ -202,6 +202,50 @@ extern bool wmi_has_guid(const char *gui
440
441 #endif /* CONFIG_ACPI_WMI */
442
443 +#define ACPI_VIDEO_OUTPUT_SWITCHING 0x0001
444 +#define ACPI_VIDEO_DEVICE_POSTING 0x0002
445 +#define ACPI_VIDEO_ROM_AVAILABLE 0x0004
446 +#define ACPI_VIDEO_BACKLIGHT 0x0008
447 +#define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR 0x0010
448 +#define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO 0x0020
449 +#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR 0x0040
450 +#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO 0x0080
451 +#define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR 0x0100
452 +#define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200
453 +#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400
454 +#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800
455 +
456 +#if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
457 +
458 +extern long acpi_video_get_capabilities(acpi_handle graphics_dev_handle);
459 +extern long acpi_is_video_device(struct acpi_device *device);
460 +extern int acpi_video_backlight_support(void);
461 +extern int acpi_video_display_switch_support(void);
462 +
463 +#else
464 +
465 +static inline long acpi_video_get_capabilities(acpi_handle graphics_dev_handle)
466 +{
467 + return 0;
468 +}
469 +
470 +static inline long acpi_is_video_device(struct acpi_device *device)
471 +{
472 + return 0;
473 +}
474 +
475 +static inline int acpi_video_backlight_support(void)
476 +{
477 + return 0;
478 +}
479 +
480 +static inline int acpi_video_display_switch_support(void)
481 +{
482 + return 0;
483 +}
484 +
485 +#endif /* defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) */
486 +
487 extern int acpi_blacklisted(void);
488 #ifdef CONFIG_DMI
489 extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);