Add patches accepted for 2.6.26-rc1
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / releases / upstream / 2.6.26-rc1 / 0002-ACPI-thinkpad-acpi-BIOS-backlight-mode-helper-v2.patch
blobd3aeb9685f52aa2d0d61da7fe9acbef5fec8c344
1 From b59727965d7f286489206c292e2788d4835a8a23 Mon Sep 17 00:00:00 2001
2 From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
3 Date: Sat, 26 Apr 2008 01:02:17 -0300
4 Subject: ACPI: thinkpad-acpi: BIOS backlight mode helper (v2.1)
6 Lenovo ThinkPads with generic ACPI backlight level control can be easily
7 set to react to keyboard brightness key presses in a more predictable way
8 than what they do when in "DOS / bootloader" mode after Linux brings
9 up the ACPI interface.
11 The switch to the ACPI backlight mode in the firmware is designed to be
12 safe to use only as an one way trapdoor. One is not to force the firmware
13 to switch back to "DOS/bootloader" mode except by rebooting. The mode
14 switch itself is performed by calling any of the ACPI _BCL methods at least
15 once.
17 When in ACPI mode, the backlight firmware just issues (standard) events for
18 the brightness up/down hot key presses along with the non-standard HKEY
19 events which thinkpad-acpi traps, and doesn't touch the hardware.
21 thinkpad-acpi will:
23 1. Place the ThinkPad firmware in ACPI backlight control mode
24 if one is available
25 2. Suppress HKEY backlight change notifications by default
26 to avoid double-reporting when ACPI video is loaded when
27 the ThinkPad is in ACPI backlight control mode
28 3. Urge the user to load the ACPI video driver
30 The user is free to use either the ACPI video driver to get the brightness
31 key events, or to override the thinkpad-acpi default hotkey mask to get
32 them from thinkpad-acpi as well (this will result in duplicate events if
33 ACPI video is loaded, so let's hope distros won't screw this up).
35 Provided userspace is sane, all should work (and *keep* working), which is
36 more that can be said about the non-ACPI mode of the new Lenovo ThinkPad
37 BIOSes when coupled to current userspace and X.org drivers.
39 Full guidelines for backlight hot key reporting and use of the
40 thinkpad-acpi backlight interface have been added to the documentation.
42 Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
43 Cc: Matthew Garrett <mjg59@srcf.ucam.org>
44 Cc: Thomas Renninger <trenn@suse.de>
45 Signed-off-by: Len Brown <len.brown@intel.com>
46 ---
47 Documentation/laptops/thinkpad-acpi.txt | 50 +++++++
48 drivers/misc/thinkpad_acpi.c | 238 +++++++++++++++++--------------
49 2 files changed, 183 insertions(+), 105 deletions(-)
51 diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
52 index 76cb428..a77da28 100644
53 --- a/Documentation/laptops/thinkpad-acpi.txt
54 +++ b/Documentation/laptops/thinkpad-acpi.txt
55 @@ -571,6 +571,47 @@ netlink interface and the input layer interface, and don't bother at all
56 with hotkey_report_mode.
59 +Brightness hotkey notes:
61 +These are the current sane choices for brightness key mapping in
62 +thinkpad-acpi:
64 +For IBM and Lenovo models *without* ACPI backlight control (the ones on
65 +which thinkpad-acpi will autoload its backlight interface by default,
66 +and on which ACPI video does not export a backlight interface):
68 +1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as
69 + these older firmware versions unfortunately won't respect the hotkey
70 + mask for brightness keys anyway, and always reacts to them. This
71 + usually work fine, unless X.org drivers are doing something to block
72 + the BIOS. In that case, use (3) below. This is the default mode of
73 + operation.
75 +2. Enable the hotkeys, but map them to something else that is NOT
76 + KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause
77 + userspace to try to change the backlight level, and use that as an
78 + on-screen-display hint.
80 +3. IF AND ONLY IF X.org drivers find a way to block the firmware from
81 + automatically changing the brightness, enable the hotkeys and map
82 + them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to
83 + something that calls xbacklight. thinkpad-acpi will not be able to
84 + change brightness in that case either, so you should disable its
85 + backlight interface.
87 +For Lenovo models *with* ACPI backlight control:
89 +1. Load up ACPI video and use that. ACPI video will report ACPI
90 + events for brightness change keys. Do not mess with thinkpad-acpi
91 + defaults in this case. thinkpad-acpi should not have anything to do
92 + with backlight events in a scenario where ACPI video is loaded:
93 + brightness hotkeys must be disabled, and the backlight interface is
94 + to be kept disabled as well. This is the default mode of operation.
96 +2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi,
97 + and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process
98 + these keys on userspace somehow (e.g. by calling xbacklight).
100 Bluetooth
101 ---------
103 @@ -1090,6 +1131,15 @@ it there will be the following attributes:
104 dim the display.
107 +WARNING:
109 + Whatever you do, do NOT ever call thinkpad-acpi backlight-level change
110 + interface and the ACPI-based backlight level change interface
111 + (available on newer BIOSes, and driven by the Linux ACPI video driver)
112 + at the same time. The two will interact in bad ways, do funny things,
113 + and maybe reduce the life of the backlight lamps by needlessly kicking
114 + its level up and down at every change.
116 Volume control -- /proc/acpi/ibm/volume
117 ---------------------------------------
119 diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
120 index 6cb7812..2c85a2e 100644
121 --- a/drivers/misc/thinkpad_acpi.c
122 +++ b/drivers/misc/thinkpad_acpi.c
123 @@ -225,6 +225,7 @@ static struct {
124 u32 light:1;
125 u32 light_status:1;
126 u32 bright_16levels:1;
127 + u32 bright_acpimode:1;
128 u32 wan:1;
129 u32 fan_ctrl_status_undef:1;
130 u32 input_device_registered:1;
131 @@ -807,6 +808,80 @@ static int parse_strtoul(const char *buf,
132 return 0;
135 +static int __init tpacpi_query_bcl_levels(acpi_handle handle)
137 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
138 + union acpi_object *obj;
139 + int rc;
141 + if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
142 + obj = (union acpi_object *)buffer.pointer;
143 + if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
144 + printk(TPACPI_ERR "Unknown _BCL data, "
145 + "please report this to %s\n", TPACPI_MAIL);
146 + rc = 0;
147 + } else {
148 + rc = obj->package.count;
150 + } else {
151 + return 0;
154 + kfree(buffer.pointer);
155 + return rc;
158 +static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
159 + u32 lvl, void *context, void **rv)
161 + char name[ACPI_PATH_SEGMENT_LENGTH];
162 + struct acpi_buffer buffer = { sizeof(name), &name };
164 + if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
165 + !strncmp("_BCL", name, sizeof(name) - 1)) {
166 + BUG_ON(!rv || !*rv);
167 + **(int **)rv = tpacpi_query_bcl_levels(handle);
168 + return AE_CTRL_TERMINATE;
169 + } else {
170 + return AE_OK;
175 + * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map
176 + */
177 +static int __init tpacpi_check_std_acpi_brightness_support(void)
179 + int status;
180 + int bcl_levels = 0;
181 + void *bcl_ptr = &bcl_levels;
183 + if (!vid_handle) {
184 + TPACPI_ACPIHANDLE_INIT(vid);
186 + if (!vid_handle)
187 + return 0;
189 + /*
190 + * Search for a _BCL method, and execute it. This is safe on all
191 + * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista
192 + * BIOS in ACPI backlight control mode. We do NOT have to care
193 + * about calling the _BCL method in an enabled video device, any
194 + * will do for our purposes.
195 + */
197 + status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
198 + tpacpi_acpi_walk_find_bcl, NULL,
199 + &bcl_ptr);
201 + if (ACPI_SUCCESS(status) && bcl_levels > 2) {
202 + tp_features.bright_acpimode = 1;
203 + return (bcl_levels - 2);
206 + return 0;
209 /*************************************************************************
210 * thinkpad-acpi driver attributes
212 @@ -1887,6 +1962,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
213 KEY_UNKNOWN, /* 0x0D: FN+INSERT */
214 KEY_UNKNOWN, /* 0x0E: FN+DELETE */
216 + /* These either have to go through ACPI video, or
217 + * act like in the IBM ThinkPads, so don't ever
218 + * enable them by default */
219 KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
220 KEY_RESERVED, /* 0x10: FN+END (brightness down) */
222 @@ -2091,6 +2169,32 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
223 set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
226 + /* Do not issue duplicate brightness change events to
227 + * userspace */
228 + if (!tp_features.bright_acpimode)
229 + /* update bright_acpimode... */
230 + tpacpi_check_std_acpi_brightness_support();
232 + if (tp_features.bright_acpimode) {
233 + printk(TPACPI_INFO
234 + "This ThinkPad has standard ACPI backlight "
235 + "brightness control, supported by the ACPI "
236 + "video driver\n");
237 + printk(TPACPI_NOTICE
238 + "Disabling thinkpad-acpi brightness events "
239 + "by default...\n");
241 + /* The hotkey_reserved_mask change below is not
242 + * necessary while the keys are at KEY_RESERVED in the
243 + * default map, but better safe than sorry, leave it
244 + * here as a marker of what we have to do, especially
245 + * when we finally become able to set this at runtime
246 + * on response to X.org requests */
247 + hotkey_reserved_mask |=
248 + (1 << TP_ACPI_HOTKEYSCAN_FNHOME)
249 + | (1 << TP_ACPI_HOTKEYSCAN_FNEND);
252 dbg_printk(TPACPI_DBG_INIT,
253 "enabling hot key handling\n");
254 res = hotkey_status_set(1);
255 @@ -4273,100 +4377,6 @@ static struct backlight_ops ibm_backlight_data = {
257 /* --------------------------------------------------------------------- */
259 -static int __init tpacpi_query_bcll_levels(acpi_handle handle)
261 - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
262 - union acpi_object *obj;
263 - int rc;
265 - if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
266 - obj = (union acpi_object *)buffer.pointer;
267 - if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
268 - printk(TPACPI_ERR "Unknown BCLL data, "
269 - "please report this to %s\n", TPACPI_MAIL);
270 - rc = 0;
271 - } else {
272 - rc = obj->package.count;
274 - } else {
275 - return 0;
278 - kfree(buffer.pointer);
279 - return rc;
282 -static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl,
283 - void *context, void **rv)
285 - char name[ACPI_PATH_SEGMENT_LENGTH];
286 - struct acpi_buffer buffer = { sizeof(name), &name };
288 - if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
289 - !strncmp("BCLL", name, sizeof(name) - 1)) {
290 - if (tpacpi_query_bcll_levels(handle) == 16) {
291 - *rv = handle;
292 - return AE_CTRL_TERMINATE;
293 - } else {
294 - return AE_OK;
296 - } else {
297 - return AE_OK;
301 -static int __init brightness_check_levels(void)
303 - int status;
304 - void *found_node = NULL;
306 - if (!vid_handle) {
307 - TPACPI_ACPIHANDLE_INIT(vid);
309 - if (!vid_handle)
310 - return 0;
312 - /* Search for a BCLL package with 16 levels */
313 - status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3,
314 - brightness_find_bcll, NULL,
315 - &found_node);
317 - return (ACPI_SUCCESS(status) && found_node != NULL);
320 -static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl,
321 - void *context, void **rv)
323 - char name[ACPI_PATH_SEGMENT_LENGTH];
324 - struct acpi_buffer buffer = { sizeof(name), &name };
326 - if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
327 - !strncmp("_BCL", name, sizeof(name) - 1)) {
328 - *rv = handle;
329 - return AE_CTRL_TERMINATE;
330 - } else {
331 - return AE_OK;
335 -static int __init brightness_check_std_acpi_support(void)
337 - int status;
338 - void *found_node = NULL;
340 - if (!vid_handle) {
341 - TPACPI_ACPIHANDLE_INIT(vid);
343 - if (!vid_handle)
344 - return 0;
346 - /* Search for a _BCL method, but don't execute it */
347 - status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
348 - brightness_find_bcl, NULL, &found_node);
350 - return (ACPI_SUCCESS(status) && found_node != NULL);
353 static int __init brightness_init(struct ibm_init_struct *iibm)
355 int b;
356 @@ -4375,13 +4385,19 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
358 mutex_init(&brightness_mutex);
360 - if (!brightness_enable) {
361 - dbg_printk(TPACPI_DBG_INIT,
362 - "brightness support disabled by "
363 - "module parameter\n");
364 - return 1;
365 - } else if (brightness_enable > 1) {
366 - if (brightness_check_std_acpi_support()) {
367 + /*
368 + * We always attempt to detect acpi support, so as to switch
369 + * Lenovo Vista BIOS to ACPI brightness mode even if we are not
370 + * going to publish a backlight interface
371 + */
372 + b = tpacpi_check_std_acpi_brightness_support();
373 + if (b > 0) {
374 + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
375 + printk(TPACPI_NOTICE
376 + "Lenovo BIOS switched to ACPI backlight "
377 + "control mode\n");
379 + if (brightness_enable > 1) {
380 printk(TPACPI_NOTICE
381 "standard ACPI backlight interface "
382 "available, not loading native one...\n");
383 @@ -4389,6 +4405,22 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
387 + if (!brightness_enable) {
388 + dbg_printk(TPACPI_DBG_INIT,
389 + "brightness support disabled by "
390 + "module parameter\n");
391 + return 1;
394 + if (b > 16) {
395 + printk(TPACPI_ERR
396 + "Unsupported brightness interface, "
397 + "please contact %s\n", TPACPI_MAIL);
398 + return 1;
400 + if (b == 16)
401 + tp_features.bright_16levels = 1;
403 if (!brightness_mode) {
404 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO)
405 brightness_mode = 2;
406 @@ -4402,10 +4434,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
407 if (brightness_mode > 3)
408 return -EINVAL;
410 - tp_features.bright_16levels =
411 - thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO &&
412 - brightness_check_levels();
414 b = brightness_get(NULL);
415 if (b < 0)
416 return 1;
418 1.5.4.4