aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-29 13:47:25 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-29 13:47:25 -0400
commit6b06d2cc6d52830e3e0c001006b26255f47184dd (patch)
tree2df1fbc87b1d83b97b230c207dbe795e2c5c6423
parentb9099ff63c75216d6ca10bce5a1abcd9293c27e6 (diff)
parentaac60c11132d7ab0776cf036ac9fd6113a210859 (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (105 commits) sonypi: use mutex instead of semaphore sony-laptop: remove user visible camera controls as platform attributes meye: make meye use sony-laptop instead of sonypi sony-laptop: add a meye-usable include file for camera ops sony-laptop: complete the motion eye camera support in sony-laptop sonypi: try to detect if sony-laptop has already taken one of the known ioports sonypi: suggest sonypi users to try sony-laptop instead sony-laptop: add edge modem support (also called WWAN) sony-laptop: add locking on accesses to the ioport and global vars sony-laptop: add camera enable/disable parameter, better handle possible infinite loop thinkpad-acpi: make drivers/misc/thinkpad_acpi:fan_mutex static ACPI: thinkpad-acpi: add sysfs support to wan and bluetooth subdrivers ACPI: thinkpad-acpi: add sysfs support to hotkey subdriver ACPI: thinkpad-acpi: improve dock subdriver initialization ACPI: thinkpad-acpi: improve debugging for acpi helpers ACPI: thinkpad-acpi: improve fan control documentation ACPI: thinkpad-acpi: map ENXIO to EINVAL for fan sysfs ACPI: thinkpad-acpi: fix a fan watchdog invocation ACPI: thinkpad-acpi: do not arm fan watchdog if it would not work ACPI: thinkpad-acpi: add a fan-control feature master toggle ...
-rw-r--r--Documentation/kernel-parameters.txt32
-rw-r--r--Documentation/sony-laptop.txt25
-rw-r--r--Documentation/thinkpad-acpi.txt (renamed from Documentation/ibm-acpi.txt)585
-rw-r--r--Documentation/video4linux/meye.txt7
-rw-r--r--MAINTAINERS18
-rw-r--r--arch/i386/kernel/acpi/earlyquirk.c5
-rw-r--r--drivers/acpi/Kconfig44
-rw-r--r--drivers/acpi/Makefile10
-rw-r--r--drivers/acpi/acpi_memhotplug.c13
-rw-r--r--drivers/acpi/bus.c4
-rw-r--r--drivers/acpi/container.c6
-rw-r--r--drivers/acpi/dock.c25
-rw-r--r--drivers/acpi/ec.c495
-rw-r--r--drivers/acpi/i2c_ec.c403
-rw-r--r--drivers/acpi/i2c_ec.h23
-rw-r--r--drivers/acpi/ibm_acpi.c2798
-rw-r--r--drivers/acpi/processor_core.c4
-rw-r--r--drivers/acpi/processor_idle.c8
-rw-r--r--drivers/acpi/sbs.c1291
-rw-r--r--drivers/acpi/scan.c4
-rw-r--r--drivers/acpi/sleep/proc.c16
-rw-r--r--drivers/acpi/tables/tbfadt.c12
-rw-r--r--drivers/char/sonypi.c53
-rw-r--r--drivers/clocksource/acpi_pm.c2
-rw-r--r--drivers/media/video/Kconfig6
-rw-r--r--drivers/media/video/meye.c62
-rw-r--r--drivers/media/video/meye.h2
-rw-r--r--drivers/misc/Kconfig66
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/asus-laptop.c151
-rw-r--r--drivers/misc/sony-laptop.c2131
-rw-r--r--drivers/misc/thinkpad_acpi.c4312
-rw-r--r--drivers/misc/thinkpad_acpi.h572
-rw-r--r--drivers/pci/pci-acpi.c4
-rw-r--r--include/acpi/actbl.h1
-rw-r--r--include/linux/sony-laptop.h34
36 files changed, 8496 insertions, 4729 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 2017942e0966..84c3bd05c639 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -181,19 +181,41 @@ and is between 256 and 4096 characters. It is defined in the file
181 that require a timer override, but don't have 181 that require a timer override, but don't have
182 HPET 182 HPET
183 183
184 acpi_dbg_layer= [HW,ACPI] 184 acpi.debug_layer= [HW,ACPI]
185 Format: <int> 185 Format: <int>
186 Each bit of the <int> indicates an ACPI debug layer, 186 Each bit of the <int> indicates an ACPI debug layer,
187 1: enable, 0: disable. It is useful for boot time 187 1: enable, 0: disable. It is useful for boot time
188 debugging. After system has booted up, it can be set 188 debugging. After system has booted up, it can be set
189 via /proc/acpi/debug_layer. 189 via /sys/module/acpi/parameters/debug_layer.
190 190 CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
191 acpi_dbg_level= [HW,ACPI] 191 Available bits (add the numbers together) to enable debug output
192 for specific parts of the ACPI subsystem:
193 0x01 utilities 0x02 hardware 0x04 events 0x08 tables
194 0x10 namespace 0x20 parser 0x40 dispatcher
195 0x80 executer 0x100 resources 0x200 acpica debugger
196 0x400 os services 0x800 acpica disassembler.
197 The number can be in decimal or prefixed with 0x in hex.
198 Warning: Many of these options can produce a lot of
199 output and make your system unusable. Be very careful.
200
201 acpi.debug_level= [HW,ACPI]
192 Format: <int> 202 Format: <int>
193 Each bit of the <int> indicates an ACPI debug level, 203 Each bit of the <int> indicates an ACPI debug level,
194 1: enable, 0: disable. It is useful for boot time 204 1: enable, 0: disable. It is useful for boot time
195 debugging. After system has booted up, it can be set 205 debugging. After system has booted up, it can be set
196 via /proc/acpi/debug_level. 206 via /sys/module/acpi/parameters/debug_level.
207 CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
208 Available bits (add the numbers together) to enable different
209 debug output levels of the ACPI subsystem:
210 0x01 error 0x02 warn 0x04 init 0x08 debug object
211 0x10 info 0x20 init names 0x40 parse 0x80 load
212 0x100 dispatch 0x200 execute 0x400 names 0x800 operation region
213 0x1000 bfield 0x2000 tables 0x4000 values 0x8000 objects
214 0x10000 resources 0x20000 user requests 0x40000 package.
215 The number can be in decimal or prefixed with 0x in hex.
216 Warning: Many of these options can produce a lot of
217 output and make your system unusable. Be very careful.
218
197 219
198 acpi_fake_ecdt [HW,ACPI] Workaround failure due to BIOS lacking ECDT 220 acpi_fake_ecdt [HW,ACPI] Workaround failure due to BIOS lacking ECDT
199 221
diff --git a/Documentation/sony-laptop.txt b/Documentation/sony-laptop.txt
index dfd26df056f4..7a5c1a81905c 100644
--- a/Documentation/sony-laptop.txt
+++ b/Documentation/sony-laptop.txt
@@ -3,12 +3,18 @@ Sony Notebook Control Driver (SNC) Readme
3 Copyright (C) 2004- 2005 Stelian Pop <stelian@popies.net> 3 Copyright (C) 2004- 2005 Stelian Pop <stelian@popies.net>
4 Copyright (C) 2007 Mattia Dongili <malattia@linux.it> 4 Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
5 5
6This mini-driver drives the SNC device present in the ACPI BIOS of 6This mini-driver drives the SNC and SPIC device present in the ACPI BIOS of the
7the Sony Vaio laptops. 7Sony Vaio laptops. This driver mixes both devices functions under the same
8(hopefully consistent) interface. This also means that the sonypi driver is
9obsoleted by sony-laptop now.
8 10
9It gives access to some extra laptop functionalities. In its current 11Fn keys (hotkeys):
10form, this driver let the user set or query the screen brightness 12------------------
11through the backlight subsystem and remove/apply power to some devices. 13Some models report hotkeys through the SNC or SPIC devices, such events are
14reported both through the ACPI subsystem as acpi events and through the INPUT
15subsystem. See the logs of acpid or /proc/acpi/event and
16/proc/bus/input/devices to find out what those events are and which input
17devices are created by the driver.
12 18
13Backlight control: 19Backlight control:
14------------------ 20------------------
@@ -39,6 +45,8 @@ The files are:
39 audiopower power on/off the internal sound card 45 audiopower power on/off the internal sound card
40 lanpower power on/off the internal ethernet card 46 lanpower power on/off the internal ethernet card
41 (only in debug mode) 47 (only in debug mode)
48 bluetoothpower power on/off the internal bluetooth device
49 fanspeed get/set the fan speed
42 50
43Note that some files may be missing if they are not supported 51Note that some files may be missing if they are not supported
44by your particular laptop model. 52by your particular laptop model.
@@ -76,9 +84,9 @@ The sony-laptop driver creates, for some of those methods (the most
76current ones found on several Vaio models), an entry under 84current ones found on several Vaio models), an entry under
77/sys/devices/platform/sony-laptop, just like the 'cdpower' one. 85/sys/devices/platform/sony-laptop, just like the 'cdpower' one.
78You can create other entries corresponding to your own laptop methods by 86You can create other entries corresponding to your own laptop methods by
79further editing the source (see the 'sony_acpi_values' table, and add a new 87further editing the source (see the 'sony_nc_values' table, and add a new
80entry to this table with your get/set method names using the 88entry to this table with your get/set method names using the
81HANDLE_NAMES macro). 89SNC_HANDLE_NAMES macro).
82 90
83Your mission, should you accept it, is to try finding out what 91Your mission, should you accept it, is to try finding out what
84those entries are for, by reading/writing random values from/to those 92those entries are for, by reading/writing random values from/to those
@@ -87,6 +95,9 @@ files and find out what is the impact on your laptop.
87Should you find anything interesting, please report it back to me, 95Should you find anything interesting, please report it back to me,
88I will not disavow all knowledge of your actions :) 96I will not disavow all knowledge of your actions :)
89 97
98See also http://www.linux.it/~malattia/wiki/index.php/Sony_drivers for other
99useful info.
100
90Bugs/Limitations: 101Bugs/Limitations:
91----------------- 102-----------------
92 103
diff --git a/Documentation/ibm-acpi.txt b/Documentation/thinkpad-acpi.txt
index 0132d363feb5..2d4803359a04 100644
--- a/Documentation/ibm-acpi.txt
+++ b/Documentation/thinkpad-acpi.txt
@@ -1,16 +1,22 @@
1 IBM ThinkPad ACPI Extras Driver 1 ThinkPad ACPI Extras Driver
2 2
3 Version 0.12 3 Version 0.14
4 17 August 2005 4 April 21st, 2007
5 5
6 Borislav Deianov <borislav@users.sf.net> 6 Borislav Deianov <borislav@users.sf.net>
7 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
7 http://ibm-acpi.sf.net/ 8 http://ibm-acpi.sf.net/
8 9
9 10
10This is a Linux ACPI driver for the IBM ThinkPad laptops. It supports 11This is a Linux driver for the IBM and Lenovo ThinkPad laptops. It
11various features of these laptops which are accessible through the 12supports various features of these laptops which are accessible
12ACPI framework but not otherwise supported by the generic Linux ACPI 13through the ACPI and ACPI EC framework, but not otherwise fully
13drivers. 14supported by the generic Linux ACPI drivers.
15
16This driver used to be named ibm-acpi until kernel 2.6.21 and release
170.13-20070314. It used to be in the drivers/acpi tree, but it was
18moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel
192.6.22, and release 0.14.
14 20
15 21
16Status 22Status
@@ -21,7 +27,7 @@ detailed description):
21 27
22 - Fn key combinations 28 - Fn key combinations
23 - Bluetooth enable and disable 29 - Bluetooth enable and disable
24 - video output switching, expansion control 30 - video output switching, expansion control
25 - ThinkLight on and off 31 - ThinkLight on and off
26 - limited docking and undocking 32 - limited docking and undocking
27 - UltraBay eject 33 - UltraBay eject
@@ -32,7 +38,7 @@ detailed description):
32 - Experimental: embedded controller register dump 38 - Experimental: embedded controller register dump
33 - LCD brightness control 39 - LCD brightness control
34 - Volume control 40 - Volume control
35 - Experimental: fan speed, fan enable/disable 41 - Fan control and monitoring: fan speed, fan enable/disable
36 - Experimental: WAN enable and disable 42 - Experimental: WAN enable and disable
37 43
38A compatibility table by model and feature is maintained on the web 44A compatibility table by model and feature is maintained on the web
@@ -42,6 +48,8 @@ Please include the following information in your report:
42 48
43 - ThinkPad model name 49 - ThinkPad model name
44 - a copy of your DSDT, from /proc/acpi/dsdt 50 - a copy of your DSDT, from /proc/acpi/dsdt
51 - a copy of the output of dmidecode, with serial numbers
52 and UUIDs masked off
45 - which driver features work and which don't 53 - which driver features work and which don't
46 - the observed behavior of non-working features 54 - the observed behavior of non-working features
47 55
@@ -52,25 +60,85 @@ Installation
52------------ 60------------
53 61
54If you are compiling this driver as included in the Linux kernel 62If you are compiling this driver as included in the Linux kernel
55sources, simply enable the CONFIG_ACPI_IBM option (Power Management / 63sources, simply enable the CONFIG_THINKPAD_ACPI option, and optionally
56ACPI / IBM ThinkPad Laptop Extras). 64enable the CONFIG_THINKPAD_ACPI_BAY option if you want the
65thinkpad-specific bay functionality.
57 66
58Features 67Features
59-------- 68--------
60 69
61The driver creates the /proc/acpi/ibm directory. There is a file under 70The driver exports two different interfaces to userspace, which can be
62that directory for each feature described below. Note that while the 71used to access the features it provides. One is a legacy procfs-based
63driver is still in the alpha stage, the exact proc file format and 72interface, which will be removed at some time in the distant future.
64commands supported by the various features is guaranteed to change 73The other is a new sysfs-based interface which is not complete yet.
65frequently.
66 74
67Driver version -- /proc/acpi/ibm/driver 75The procfs interface creates the /proc/acpi/ibm directory. There is a
68--------------------------------------- 76file under that directory for each feature it supports. The procfs
77interface is mostly frozen, and will change very little if at all: it
78will not be extended to add any new functionality in the driver, instead
79all new functionality will be implemented on the sysfs interface.
80
81The sysfs interface tries to blend in the generic Linux sysfs subsystems
82and classes as much as possible. Since some of these subsystems are not
83yet ready or stabilized, it is expected that this interface will change,
84and any and all userspace programs must deal with it.
85
86
87Notes about the sysfs interface:
88
89Unlike what was done with the procfs interface, correctness when talking
90to the sysfs interfaces will be enforced, as will correctness in the
91thinkpad-acpi's implementation of sysfs interfaces.
92
93Also, any bugs in the thinkpad-acpi sysfs driver code or in the
94thinkpad-acpi's implementation of the sysfs interfaces will be fixed for
95maximum correctness, even if that means changing an interface in
96non-compatible ways. As these interfaces mature both in the kernel and
97in thinkpad-acpi, such changes should become quite rare.
98
99Applications interfacing to the thinkpad-acpi sysfs interfaces must
100follow all sysfs guidelines and correctly process all errors (the sysfs
101interface makes extensive use of errors). File descriptors and open /
102close operations to the sysfs inodes must also be properly implemented.
103
104The version of thinkpad-acpi's sysfs interface is exported by the driver
105as a driver attribute (see below).
106
107Sysfs driver attributes are on the driver's sysfs attribute space,
108for 2.6.20 this is /sys/bus/platform/drivers/thinkpad-acpi/.
109
110Sysfs device attributes are on the driver's sysfs attribute space,
111for 2.6.20 this is /sys/devices/platform/thinkpad-acpi/.
112
113Driver version
114--------------
115
116procfs: /proc/acpi/ibm/driver
117sysfs driver attribute: version
69 118
70The driver name and version. No commands can be written to this file. 119The driver name and version. No commands can be written to this file.
71 120
72Hot keys -- /proc/acpi/ibm/hotkey 121Sysfs interface version
73--------------------------------- 122-----------------------
123
124sysfs driver attribute: interface_version
125
126Version of the thinkpad-acpi sysfs interface, as an unsigned long
127(output in hex format: 0xAAAABBCC), where:
128 AAAA - major revision
129 BB - minor revision
130 CC - bugfix revision
131
132The sysfs interface version changelog for the driver can be found at the
133end of this document. Changes to the sysfs interface done by the kernel
134subsystems are not documented here, nor are they tracked by this
135attribute.
136
137Hot keys
138--------
139
140procfs: /proc/acpi/ibm/hotkey
141sysfs device attribute: hotkey/*
74 142
75Without this driver, only the Fn-F4 key (sleep button) generates an 143Without this driver, only the Fn-F4 key (sleep button) generates an
76ACPI event. With the driver loaded, the hotkey feature enabled and the 144ACPI event. With the driver loaded, the hotkey feature enabled and the
@@ -84,15 +152,6 @@ All labeled Fn-Fx key combinations generate distinct events. In
84addition, the lid microswitch and some docking station buttons may 152addition, the lid microswitch and some docking station buttons may
85also generate such events. 153also generate such events.
86 154
87The following commands can be written to this file:
88
89 echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature
90 echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature
91 echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys
92 echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
93 ... any other 4-hex-digit mask ...
94 echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
95
96The bit mask allows some control over which hot keys generate ACPI 155The bit mask allows some control over which hot keys generate ACPI
97events. Not all bits in the mask can be modified. Not all bits that 156events. Not all bits in the mask can be modified. Not all bits that
98can be modified do anything. Not all hot keys can be individually 157can be modified do anything. Not all hot keys can be individually
@@ -124,15 +183,77 @@ buttons do not generate ACPI events even with this driver. They *can*
124be used through the "ThinkPad Buttons" utility, see 183be used through the "ThinkPad Buttons" utility, see
125http://www.nongnu.org/tpb/ 184http://www.nongnu.org/tpb/
126 185
127Bluetooth -- /proc/acpi/ibm/bluetooth 186procfs notes:
128------------------------------------- 187
188The following commands can be written to the /proc/acpi/ibm/hotkey file:
189
190 echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature
191 echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature
192 echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys
193 echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
194 ... any other 4-hex-digit mask ...
195 echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
196
197sysfs notes:
198
199 The hot keys attributes are in a hotkey/ subdirectory off the
200 thinkpad device.
201
202 bios_enabled:
203 Returns the status of the hot keys feature when
204 thinkpad-acpi was loaded. Upon module unload, the hot
205 key feature status will be restored to this value.
206
207 0: hot keys were disabled
208 1: hot keys were enabled
209
210 bios_mask:
211 Returns the hot keys mask when thinkpad-acpi was loaded.
212 Upon module unload, the hot keys mask will be restored
213 to this value.
214
215 enable:
216 Enables/disables the hot keys feature, and reports
217 current status of the hot keys feature.
218
219 0: disables the hot keys feature / feature disabled
220 1: enables the hot keys feature / feature enabled
221
222 mask:
223 bit mask to enable ACPI event generation for each hot
224 key (see above). Returns the current status of the hot
225 keys mask, and allows one to modify it.
226
129 227
130This feature shows the presence and current state of a Bluetooth 228Bluetooth
131device. If Bluetooth is installed, the following commands can be used: 229---------
230
231procfs: /proc/acpi/ibm/bluetooth
232sysfs device attribute: bluetooth/enable
233
234This feature shows the presence and current state of a ThinkPad
235Bluetooth device in the internal ThinkPad CDC slot.
236
237Procfs notes:
238
239If Bluetooth is installed, the following commands can be used:
132 240
133 echo enable > /proc/acpi/ibm/bluetooth 241 echo enable > /proc/acpi/ibm/bluetooth
134 echo disable > /proc/acpi/ibm/bluetooth 242 echo disable > /proc/acpi/ibm/bluetooth
135 243
244Sysfs notes:
245
246 If the Bluetooth CDC card is installed, it can be enabled /
247 disabled through the "bluetooth/enable" thinkpad-acpi device
248 attribute, and its current status can also be queried.
249
250 enable:
251 0: disables Bluetooth / Bluetooth is disabled
252 1: enables Bluetooth / Bluetooth is enabled.
253
254 Note: this interface will be probably be superseeded by the
255 generic rfkill class.
256
136Video output control -- /proc/acpi/ibm/video 257Video output control -- /proc/acpi/ibm/video
137-------------------------------------------- 258--------------------------------------------
138 259
@@ -209,7 +330,7 @@ hot plugging of devices in the Linux ACPI framework. If the laptop was
209booted while not in the dock, the following message is shown in the 330booted while not in the dock, the following message is shown in the
210logs: 331logs:
211 332
212 Mar 17 01:42:34 aero kernel: ibm_acpi: dock device not present 333 Mar 17 01:42:34 aero kernel: thinkpad_acpi: dock device not present
213 334
214In this case, no dock-related events are generated but the dock and 335In this case, no dock-related events are generated but the dock and
215undock commands described below still work. They can be executed 336undock commands described below still work. They can be executed
@@ -269,7 +390,7 @@ This is due to the current lack of support for hot plugging of devices
269in the Linux ACPI framework. If the laptop was booted without the 390in the Linux ACPI framework. If the laptop was booted without the
270UltraBay, the following message is shown in the logs: 391UltraBay, the following message is shown in the logs:
271 392
272 Mar 17 01:42:34 aero kernel: ibm_acpi: bay device not present 393 Mar 17 01:42:34 aero kernel: thinkpad_acpi: bay device not present
273 394
274In this case, no bay-related events are generated but the eject 395In this case, no bay-related events are generated but the eject
275command described below still works. It can be executed manually or 396command described below still works. It can be executed manually or
@@ -313,23 +434,19 @@ supported. Use "eject2" instead of "eject" for the second bay.
313Note: the UltraBay eject support on the 600e/x, A22p and A3x is 434Note: the UltraBay eject support on the 600e/x, A22p and A3x is
314EXPERIMENTAL and may not work as expected. USE WITH CAUTION! 435EXPERIMENTAL and may not work as expected. USE WITH CAUTION!
315 436
316CMOS control -- /proc/acpi/ibm/cmos 437CMOS control
317----------------------------------- 438------------
439
440procfs: /proc/acpi/ibm/cmos
441sysfs device attribute: cmos_command
318 442
319This feature is used internally by the ACPI firmware to control the 443This feature is used internally by the ACPI firmware to control the
320ThinkLight on most newer ThinkPad models. It may also control LCD 444ThinkLight on most newer ThinkPad models. It may also control LCD
321brightness, sounds volume and more, but only on some models. 445brightness, sounds volume and more, but only on some models.
322 446
323The commands are non-negative integer numbers: 447The range of valid cmos command numbers is 0 to 21, but not all have an
324 448effect and the behavior varies from model to model. Here is the behavior
325 echo 0 >/proc/acpi/ibm/cmos 449on the X40 (tpb is the ThinkPad Buttons utility):
326 echo 1 >/proc/acpi/ibm/cmos
327 echo 2 >/proc/acpi/ibm/cmos
328 ...
329
330The range of valid numbers is 0 to 21, but not all have an effect and
331the behavior varies from model to model. Here is the behavior on the
332X40 (tpb is the ThinkPad Buttons utility):
333 450
334 0 - no effect but tpb reports "Volume down" 451 0 - no effect but tpb reports "Volume down"
335 1 - no effect but tpb reports "Volume up" 452 1 - no effect but tpb reports "Volume up"
@@ -342,6 +459,9 @@ X40 (tpb is the ThinkPad Buttons utility):
342 13 - ThinkLight off 459 13 - ThinkLight off
343 14 - no effect but tpb reports ThinkLight status change 460 14 - no effect but tpb reports ThinkLight status change
344 461
462The cmos command interface is prone to firmware split-brain problems, as
463in newer ThinkPads it is just a compatibility layer.
464
345LED control -- /proc/acpi/ibm/led 465LED control -- /proc/acpi/ibm/led
346--------------------------------- 466---------------------------------
347 467
@@ -393,17 +513,17 @@ X40:
393 16 - one medium-pitched beep repeating constantly, stop with 17 513 16 - one medium-pitched beep repeating constantly, stop with 17
394 17 - stop 16 514 17 - stop 16
395 515
396Temperature sensors -- /proc/acpi/ibm/thermal 516Temperature sensors
397--------------------------------------------- 517-------------------
518
519procfs: /proc/acpi/ibm/thermal
520sysfs device attributes: (hwmon) temp*_input
398 521
399Most ThinkPads include six or more separate temperature sensors but 522Most ThinkPads include six or more separate temperature sensors but
400only expose the CPU temperature through the standard ACPI methods. 523only expose the CPU temperature through the standard ACPI methods.
401This feature shows readings from up to eight different sensors on older 524This feature shows readings from up to eight different sensors on older
402ThinkPads, and it has experimental support for up to sixteen different 525ThinkPads, and it has experimental support for up to sixteen different
403sensors on newer ThinkPads. Readings from sensors that are not available 526sensors on newer ThinkPads.
404return -128.
405
406No commands can be written to this file.
407 527
408EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the 528EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the
409implementation directly accesses hardware registers and may not work as 529implementation directly accesses hardware registers and may not work as
@@ -460,6 +580,20 @@ The A31 has a very atypical layout for the thermal sensors
4608: Bay Battery: secondary sensor 5808: Bay Battery: secondary sensor
461 581
462 582
583Procfs notes:
584 Readings from sensors that are not available return -128.
585 No commands can be written to this file.
586
587Sysfs notes:
588 Sensors that are not available return the ENXIO error. This
589 status may change at runtime, as there are hotplug thermal
590 sensors, like those inside the batteries and docks.
591
592 thinkpad-acpi thermal sensors are reported through the hwmon
593 subsystem, and follow all of the hwmon guidelines at
594 Documentation/hwmon.
595
596
463EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump 597EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump
464------------------------------------------------------------------------ 598------------------------------------------------------------------------
465 599
@@ -472,7 +606,7 @@ This feature dumps the values of 256 embedded controller
472registers. Values which have changed since the last time the registers 606registers. Values which have changed since the last time the registers
473were dumped are marked with a star: 607were dumped are marked with a star:
474 608
475[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump 609[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
476EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f 610EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
477EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00 611EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00
478EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00 612EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00
@@ -503,7 +637,7 @@ vary. The second ensures that the fan-related values do vary, since
503the fan speed fluctuates a bit. The third will (hopefully) mark the 637the fan speed fluctuates a bit. The third will (hopefully) mark the
504fan register with a star: 638fan register with a star:
505 639
506[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump 640[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
507EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f 641EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
508EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00 642EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00
509EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00 643EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00
@@ -533,19 +667,59 @@ registers contain the current battery capacity, etc. If you experiment
533with this, do send me your results (including some complete dumps with 667with this, do send me your results (including some complete dumps with
534a description of the conditions when they were taken.) 668a description of the conditions when they were taken.)
535 669
536LCD brightness control -- /proc/acpi/ibm/brightness 670LCD brightness control
537--------------------------------------------------- 671----------------------
672
673procfs: /proc/acpi/ibm/brightness
674sysfs backlight device "thinkpad_screen"
538 675
539This feature allows software control of the LCD brightness on ThinkPad 676This feature allows software control of the LCD brightness on ThinkPad
540models which don't have a hardware brightness slider. The available 677models which don't have a hardware brightness slider.
541commands are: 678
679It has some limitations: the LCD backlight cannot be actually turned on or off
680by this interface, and in many ThinkPad models, the "dim while on battery"
681functionality will be enabled by the BIOS when this interface is used, and
682cannot be controlled.
683
684The backlight control has eight levels, ranging from 0 to 7. Some of the
685levels may not be distinct.
686
687Procfs notes:
688
689 The available commands are:
542 690
543 echo up >/proc/acpi/ibm/brightness 691 echo up >/proc/acpi/ibm/brightness
544 echo down >/proc/acpi/ibm/brightness 692 echo down >/proc/acpi/ibm/brightness
545 echo 'level <level>' >/proc/acpi/ibm/brightness 693 echo 'level <level>' >/proc/acpi/ibm/brightness
546 694
547The <level> number range is 0 to 7, although not all of them may be 695Sysfs notes:
548distinct. The current brightness level is shown in the file. 696
697The interface is implemented through the backlight sysfs class, which is poorly
698documented at this time.
699
700Locate the thinkpad_screen device under /sys/class/backlight, and inside it
701there will be the following attributes:
702
703 max_brightness:
704 Reads the maximum brightness the hardware can be set to.
705 The minimum is always zero.
706
707 actual_brightness:
708 Reads what brightness the screen is set to at this instant.
709
710 brightness:
711 Writes request the driver to change brightness to the given
712 value. Reads will tell you what brightness the driver is trying
713 to set the display to when "power" is set to zero and the display
714 has not been dimmed by a kernel power management event.
715
716 power:
717 power management mode, where 0 is "display on", and 1 to 3 will
718 dim the display backlight to brightness level 0 because
719 thinkpad-acpi cannot really turn the backlight off. Kernel
720 power management events can temporarily increase the current
721 power management level, i.e. they can dim the display.
722
549 723
550Volume control -- /proc/acpi/ibm/volume 724Volume control -- /proc/acpi/ibm/volume
551--------------------------------------- 725---------------------------------------
@@ -563,41 +737,42 @@ distinct. The unmute the volume after the mute command, use either the
563up or down command (the level command will not unmute the volume). 737up or down command (the level command will not unmute the volume).
564The current volume level and mute state is shown in the file. 738The current volume level and mute state is shown in the file.
565 739
566EXPERIMENTAL: fan speed, fan enable/disable -- /proc/acpi/ibm/fan 740Fan control and monitoring: fan speed, fan enable/disable
567----------------------------------------------------------------- 741---------------------------------------------------------
568 742
569This feature is marked EXPERIMENTAL because the implementation 743procfs: /proc/acpi/ibm/fan
570directly accesses hardware registers and may not work as expected. USE 744sysfs device attributes: (hwmon) fan_input, pwm1, pwm1_enable
571WITH CAUTION! To use this feature, you need to supply the 745
572experimental=1 parameter when loading the module. 746NOTE NOTE NOTE: fan control operations are disabled by default for
747safety reasons. To enable them, the module parameter "fan_control=1"
748must be given to thinkpad-acpi.
573 749
574This feature attempts to show the current fan speed, control mode and 750This feature attempts to show the current fan speed, control mode and
575other fan data that might be available. The speed is read directly 751other fan data that might be available. The speed is read directly
576from the hardware registers of the embedded controller. This is known 752from the hardware registers of the embedded controller. This is known
577to work on later R, T and X series ThinkPads but may show a bogus 753to work on later R, T, X and Z series ThinkPads but may show a bogus
578value on other models. 754value on other models.
579 755
580Most ThinkPad fans work in "levels". Level 0 stops the fan. The higher 756Fan levels:
581the level, the higher the fan speed, although adjacent levels often map
582to the same fan speed. 7 is the highest level, where the fan reaches
583the maximum recommended speed. Level "auto" means the EC changes the
584fan level according to some internal algorithm, usually based on
585readings from the thermal sensors. Level "disengaged" means the EC
586disables the speed-locked closed-loop fan control, and drives the fan as
587fast as it can go, which might exceed hardware limits, so use this level
588with caution.
589 757
590The fan usually ramps up or down slowly from one speed to another, 758Most ThinkPad fans work in "levels" at the firmware interface. Level 0
591and it is normal for the EC to take several seconds to react to fan 759stops the fan. The higher the level, the higher the fan speed, although
592commands. 760adjacent levels often map to the same fan speed. 7 is the highest
761level, where the fan reaches the maximum recommended speed.
593 762
594The fan may be enabled or disabled with the following commands: 763Level "auto" means the EC changes the fan level according to some
764internal algorithm, usually based on readings from the thermal sensors.
595 765
596 echo enable >/proc/acpi/ibm/fan 766There is also a "full-speed" level, also known as "disengaged" level.
597 echo disable >/proc/acpi/ibm/fan 767In this level, the EC disables the speed-locked closed-loop fan control,
768and drives the fan as fast as it can go, which might exceed hardware
769limits, so use this level with caution.
598 770
599Placing a fan on level 0 is the same as disabling it. Enabling a fan 771The fan usually ramps up or down slowly from one speed to another, and
600will try to place it in a safe level if it is too slow or disabled. 772it is normal for the EC to take several seconds to react to fan
773commands. The full-speed level may take up to two minutes to ramp up to
774maximum speed, and in some ThinkPads, the tachometer readings go stale
775while the EC is transitioning to the full-speed level.
601 776
602WARNING WARNING WARNING: do not leave the fan disabled unless you are 777WARNING WARNING WARNING: do not leave the fan disabled unless you are
603monitoring all of the temperature sensor readings and you are ready to 778monitoring all of the temperature sensor readings and you are ready to
@@ -615,46 +790,146 @@ fan is turned off when the CPU temperature drops to 49 degrees and the
615HDD temperature drops to 41 degrees. These thresholds cannot 790HDD temperature drops to 41 degrees. These thresholds cannot
616currently be controlled. 791currently be controlled.
617 792
793The ThinkPad's ACPI DSDT code will reprogram the fan on its own when
794certain conditions are met. It will override any fan programming done
795through thinkpad-acpi.
796
797The thinkpad-acpi kernel driver can be programmed to revert the fan
798level to a safe setting if userspace does not issue one of the procfs
799fan commands: "enable", "disable", "level" or "watchdog", or if there
800are no writes to pwm1_enable (or to pwm1 *if and only if* pwm1_enable is
801set to 1, manual mode) within a configurable amount of time of up to
802120 seconds. This functionality is called fan safety watchdog.
803
804Note that the watchdog timer stops after it enables the fan. It will be
805rearmed again automatically (using the same interval) when one of the
806above mentioned fan commands is received. The fan watchdog is,
807therefore, not suitable to protect against fan mode changes made through
808means other than the "enable", "disable", and "level" procfs fan
809commands, or the hwmon fan control sysfs interface.
810
811Procfs notes:
812
813The fan may be enabled or disabled with the following commands:
814
815 echo enable >/proc/acpi/ibm/fan
816 echo disable >/proc/acpi/ibm/fan
817
818Placing a fan on level 0 is the same as disabling it. Enabling a fan
819will try to place it in a safe level if it is too slow or disabled.
820
618The fan level can be controlled with the command: 821The fan level can be controlled with the command:
619 822
620 echo 'level <level>' > /proc/acpi/ibm/thermal 823 echo 'level <level>' > /proc/acpi/ibm/fan
621 824
622Where <level> is an integer from 0 to 7, or one of the words "auto" 825Where <level> is an integer from 0 to 7, or one of the words "auto" or
623or "disengaged" (without the quotes). Not all ThinkPads support the 826"full-speed" (without the quotes). Not all ThinkPads support the "auto"
624"auto" and "disengaged" levels. 827and "full-speed" levels. The driver accepts "disengaged" as an alias for
828"full-speed", and reports it as "disengaged" for backwards
829compatibility.
625 830
626On the X31 and X40 (and ONLY on those models), the fan speed can be 831On the X31 and X40 (and ONLY on those models), the fan speed can be
627controlled to a certain degree. Once the fan is running, it can be 832controlled to a certain degree. Once the fan is running, it can be
628forced to run faster or slower with the following command: 833forced to run faster or slower with the following command:
629 834
630 echo 'speed <speed>' > /proc/acpi/ibm/thermal 835 echo 'speed <speed>' > /proc/acpi/ibm/fan
631 836
632The sustainable range of fan speeds on the X40 appears to be from 837The sustainable range of fan speeds on the X40 appears to be from about
633about 3700 to about 7350. Values outside this range either do not have 8383700 to about 7350. Values outside this range either do not have any
634any effect or the fan speed eventually settles somewhere in that 839effect or the fan speed eventually settles somewhere in that range. The
635range. The fan cannot be stopped or started with this command. 840fan cannot be stopped or started with this command. This functionality
841is incomplete, and not available through the sysfs interface.
636 842
637The ThinkPad's ACPI DSDT code will reprogram the fan on its own when 843To program the safety watchdog, use the "watchdog" command.
638certain conditions are met. It will override any fan programming done
639through ibm-acpi.
640 844
641EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan 845 echo 'watchdog <interval in seconds>' > /proc/acpi/ibm/fan
642--------------------------------------- 846
847If you want to disable the watchdog, use 0 as the interval.
848
849Sysfs notes:
850
851The sysfs interface follows the hwmon subsystem guidelines for the most
852part, and the exception is the fan safety watchdog.
853
854Writes to any of the sysfs attributes may return the EINVAL error if
855that operation is not supported in a given ThinkPad or if the parameter
856is out-of-bounds, and EPERM if it is forbidden. They may also return
857EINTR (interrupted system call), and EIO (I/O error while trying to talk
858to the firmware).
859
860Features not yet implemented by the driver return ENOSYS.
861
862hwmon device attribute pwm1_enable:
863 0: PWM offline (fan is set to full-speed mode)
864 1: Manual PWM control (use pwm1 to set fan level)
865 2: Hardware PWM control (EC "auto" mode)
866 3: reserved (Software PWM control, not implemented yet)
867
868 Modes 0 and 2 are not supported by all ThinkPads, and the
869 driver is not always able to detect this. If it does know a
870 mode is unsupported, it will return -EINVAL.
871
872hwmon device attribute pwm1:
873 Fan level, scaled from the firmware values of 0-7 to the hwmon
874 scale of 0-255. 0 means fan stopped, 255 means highest normal
875 speed (level 7).
876
877 This attribute only commands the fan if pmw1_enable is set to 1
878 (manual PWM control).
879
880hwmon device attribute fan1_input:
881 Fan tachometer reading, in RPM. May go stale on certain
882 ThinkPads while the EC transitions the PWM to offline mode,
883 which can take up to two minutes. May return rubbish on older
884 ThinkPads.
885
886driver attribute fan_watchdog:
887 Fan safety watchdog timer interval, in seconds. Minimum is
888 1 second, maximum is 120 seconds. 0 disables the watchdog.
889
890To stop the fan: set pwm1 to zero, and pwm1_enable to 1.
891
892To start the fan in a safe mode: set pwm1_enable to 2. If that fails
893with EINVAL, try to set pwm1_enable to 1 and pwm1 to at least 128 (255
894would be the safest choice, though).
895
896
897EXPERIMENTAL: WAN
898-----------------
899
900procfs: /proc/acpi/ibm/wan
901sysfs device attribute: wwan/enable
643 902
644This feature is marked EXPERIMENTAL because the implementation 903This feature is marked EXPERIMENTAL because the implementation
645directly accesses hardware registers and may not work as expected. USE 904directly accesses hardware registers and may not work as expected. USE
646WITH CAUTION! To use this feature, you need to supply the 905WITH CAUTION! To use this feature, you need to supply the
647experimental=1 parameter when loading the module. 906experimental=1 parameter when loading the module.
648 907
649This feature shows the presence and current state of a WAN (Sierra 908This feature shows the presence and current state of a W-WAN (Sierra
650Wireless EV-DO) device. If WAN is installed, the following commands can 909Wireless EV-DO) device.
651be used: 910
911It was tested on a Lenovo Thinkpad X60. It should probably work on other
912Thinkpad models which come with this module installed.
913
914Procfs notes:
915
916If the W-WAN card is installed, the following commands can be used:
652 917
653 echo enable > /proc/acpi/ibm/wan 918 echo enable > /proc/acpi/ibm/wan
654 echo disable > /proc/acpi/ibm/wan 919 echo disable > /proc/acpi/ibm/wan
655 920
656It was tested on a Lenovo Thinkpad X60. It should probably work on other 921Sysfs notes:
657Thinkpad models which come with this module installed. 922
923 If the W-WAN card is installed, it can be enabled /
924 disabled through the "wwan/enable" thinkpad-acpi device
925 attribute, and its current status can also be queried.
926
927 enable:
928 0: disables WWAN card / WWAN card is disabled
929 1: enables WWAN card / WWAN card is enabled.
930
931 Note: this interface will be probably be superseeded by the
932 generic rfkill class.
658 933
659Multiple Commands, Module Parameters 934Multiple Commands, Module Parameters
660------------------------------------ 935------------------------------------
@@ -665,64 +940,42 @@ separating them with commas, for example:
665 echo enable,0xffff > /proc/acpi/ibm/hotkey 940 echo enable,0xffff > /proc/acpi/ibm/hotkey
666 echo lcd_disable,crt_enable > /proc/acpi/ibm/video 941 echo lcd_disable,crt_enable > /proc/acpi/ibm/video
667 942
668Commands can also be specified when loading the ibm_acpi module, for 943Commands can also be specified when loading the thinkpad-acpi module,
669example: 944for example:
670 945
671 modprobe ibm_acpi hotkey=enable,0xffff video=auto_disable 946 modprobe thinkpad_acpi hotkey=enable,0xffff video=auto_disable
672 947
673The ibm-acpi kernel driver can be programmed to revert the fan level 948Enabling debugging output
674to a safe setting if userspace does not issue one of the fan commands: 949-------------------------
675"enable", "disable", "level" or "watchdog" within a configurable 950
676ammount of time. To do this, use the "watchdog" command. 951The module takes a debug paramater which can be used to selectively
677 952enable various classes of debugging output, for example:
678 echo 'watchdog <interval>' > /proc/acpi/ibm/fan 953
679 954 modprobe ibm_acpi debug=0xffff
680Interval is the ammount of time in seconds to wait for one of the 955
681above mentioned fan commands before reseting the fan level to a safe 956will enable all debugging output classes. It takes a bitmask, so
682one. If set to zero, the watchdog is disabled (default). When the 957to enable more than one output class, just add their values.
683watchdog timer runs out, it does the exact equivalent of the "enable" 958
684fan command. 959 Debug bitmask Description
685 960 0x0001 Initialization and probing
686Note that the watchdog timer stops after it enables the fan. It will 961 0x0002 Removal
687be rearmed again automatically (using the same interval) when one of 962
688the above mentioned fan commands is received. The fan watchdog is, 963There is also a kernel build option to enable more debugging
689therefore, not suitable to protect against fan mode changes made 964information, which may be necessary to debug driver problems.
690through means other than the "enable", "disable", and "level" fan 965
691commands. 966The level of debugging information output by the driver can be changed
692 967at runtime through sysfs, using the driver attribute debug_level. The
693 968attribute takes the same bitmask as the debug module parameter above.
694Example Configuration 969
695--------------------- 970Force loading of module
696 971-----------------------
697The ACPI support in the kernel is intended to be used in conjunction 972
698with a user-space daemon, acpid. The configuration files for this 973If thinkpad-acpi refuses to detect your ThinkPad, you can try to specify
699daemon control what actions are taken in response to various ACPI 974the module parameter force_load=1. Regardless of whether this works or
700events. An example set of configuration files are included in the 975not, please contact ibm-acpi-devel@lists.sourceforge.net with a report.
701config/ directory of the tarball package available on the web 976
702site. Note that these are provided for illustration purposes only and 977
703may need to be adapted to your particular setup. 978Sysfs interface changelog:
704 979
705The following utility scripts are used by the example action 9800x000100: Initial sysfs support, as a single platform driver and
706scripts (included with ibm-acpi for completeness): 981 device.
707
708 /usr/local/sbin/idectl -- from the hdparm source distribution,
709 see http://www.ibiblio.org/pub/Linux/system/hardware
710 /usr/local/sbin/laptop_mode -- from the Linux kernel source
711 distribution, see Documentation/laptop-mode.txt
712 /sbin/service -- comes with Redhat/Fedora distributions
713 /usr/sbin/hibernate -- from the Software Suspend 2 distribution,
714 see http://softwaresuspend.berlios.de/
715
716Toan T Nguyen <ntt@physics.ucla.edu> notes that Suse uses the
717powersave program to suspend ('powersave --suspend-to-ram') or
718hibernate ('powersave --suspend-to-disk'). This means that the
719hibernate script is not needed on that distribution.
720
721Henrik Brix Andersen <brix@gentoo.org> has written a Gentoo ACPI event
722handler script for the X31. You can get the latest version from
723http://dev.gentoo.org/~brix/files/x31.sh
724
725David Schweikert <dws@ee.eth.ch> has written an alternative blank.sh
726script which works on Debian systems. This scripts has now been
727extended to also work on Fedora systems and included as the default
728blank.sh in the distribution.
diff --git a/Documentation/video4linux/meye.txt b/Documentation/video4linux/meye.txt
index ecb34160e61d..5e51c59bf2b0 100644
--- a/Documentation/video4linux/meye.txt
+++ b/Documentation/video4linux/meye.txt
@@ -5,10 +5,9 @@ Vaio Picturebook Motion Eye Camera Driver Readme
5 Copyright (C) 2000 Andrew Tridgell <tridge@samba.org> 5 Copyright (C) 2000 Andrew Tridgell <tridge@samba.org>
6 6
7This driver enable the use of video4linux compatible applications with the 7This driver enable the use of video4linux compatible applications with the
8Motion Eye camera. This driver requires the "Sony Vaio Programmable I/O 8Motion Eye camera. This driver requires the "Sony Laptop Extras" driver (which
9Control Device" driver (which can be found in the "Character drivers" 9can be found in the "Misc devices" section of the kernel configuration utility)
10section of the kernel configuration utility) to be compiled and installed 10to be compiled and installed (using its "camera=1" parameter).
11(using its "camera=1" parameter).
12 11
13It can do at maximum 30 fps @ 320x240 or 15 fps @ 640x480. 12It can do at maximum 30 fps @ 320x240 or 15 fps @ 640x480.
14 13
diff --git a/MAINTAINERS b/MAINTAINERS
index 77bff8ce1a44..993e2a69440e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1658,15 +1658,6 @@ W: http://www.ia64-linux.org/
1658T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git 1658T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
1659S: Maintained 1659S: Maintained
1660 1660
1661IBM ACPI EXTRAS DRIVER
1662P: Henrique de Moraes Holschuh
1663M: ibm-acpi@hmh.eng.br
1664L: ibm-acpi-devel@lists.sourceforge.net
1665W: http://ibm-acpi.sourceforge.net
1666W: http://thinkwiki.org/wiki/Ibm-acpi
1667T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
1668S: Maintained
1669
1670SN-IA64 (Itanium) SUB-PLATFORM 1661SN-IA64 (Itanium) SUB-PLATFORM
1671P: Jes Sorensen 1662P: Jes Sorensen
1672M: jes@sgi.com 1663M: jes@sgi.com
@@ -3166,6 +3157,15 @@ P: Chris Zankel
3166M: chris@zankel.net 3157M: chris@zankel.net
3167S: Maintained 3158S: Maintained
3168 3159
3160THINKPAD ACPI EXTRAS DRIVER
3161P: Henrique de Moraes Holschuh
3162M: ibm-acpi@hmh.eng.br
3163L: ibm-acpi-devel@lists.sourceforge.net
3164W: http://ibm-acpi.sourceforge.net
3165W: http://thinkwiki.org/wiki/Ibm-acpi
3166T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
3167S: Maintained
3168
3169UltraSPARC (sparc64): 3169UltraSPARC (sparc64):
3170P: David S. Miller 3170P: David S. Miller
3171M: davem@davemloft.net 3171M: davem@davemloft.net
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c
index a7d22d9f3d7e..8f7efd38254d 100644
--- a/arch/i386/kernel/acpi/earlyquirk.c
+++ b/arch/i386/kernel/acpi/earlyquirk.c
@@ -23,10 +23,13 @@ static int __init nvidia_hpet_check(struct acpi_table_header *header)
23static int __init check_bridge(int vendor, int device) 23static int __init check_bridge(int vendor, int device)
24{ 24{
25#ifdef CONFIG_ACPI 25#ifdef CONFIG_ACPI
26 static int warned;
26 /* According to Nvidia all timer overrides are bogus unless HPET 27 /* According to Nvidia all timer overrides are bogus unless HPET
27 is enabled. */ 28 is enabled. */
28 if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) { 29 if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) {
29 if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) { 30 if (!warned && acpi_table_parse(ACPI_SIG_HPET,
31 nvidia_hpet_check)) {
32 warned = 1;
30 acpi_skip_timer_override = 1; 33 acpi_skip_timer_override = 1;
31 printk(KERN_INFO "Nvidia board " 34 printk(KERN_INFO "Nvidia board "
32 "detected. Ignoring ACPI " 35 "detected. Ignoring ACPI "
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index e2ce4a9c1c92..139f41f033d8 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -85,8 +85,8 @@ config ACPI_PROCFS
85 depends on ACPI 85 depends on ACPI
86 default y 86 default y
87 ---help--- 87 ---help---
88 Procfs interface for ACPI is made optional for back-compatible. 88 The Procfs interface for ACPI is made optional for backward compatibility.
89 As the same functions are duplicated in sysfs interface 89 As the same functions are duplicated in the sysfs interface
90 and this proc interface will be removed some time later, 90 and this proc interface will be removed some time later,
91 it's marked as deprecated. 91 it's marked as deprecated.
92 ( /proc/acpi/debug_layer && debug_level are deprecated by 92 ( /proc/acpi/debug_layer && debug_level are deprecated by
@@ -218,43 +218,6 @@ config ACPI_ASUS
218 NOTE: This driver is deprecated and will probably be removed soon, 218 NOTE: This driver is deprecated and will probably be removed soon,
219 use asus-laptop instead. 219 use asus-laptop instead.
220 220
221config ACPI_IBM
222 tristate "IBM ThinkPad Laptop Extras"
223 depends on X86
224 select BACKLIGHT_CLASS_DEVICE
225 ---help---
226 This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
227 support for Fn-Fx key combinations, Bluetooth control, video
228 output switching, ThinkLight control, UltraBay eject and more.
229 For more information about this driver see <file:Documentation/ibm-acpi.txt>
230 and <http://ibm-acpi.sf.net/> .
231
232 If you have an IBM ThinkPad laptop, say Y or M here.
233
234config ACPI_IBM_DOCK
235 bool "Legacy Docking Station Support"
236 depends on ACPI_IBM
237 depends on ACPI_DOCK=n
238 default n
239 ---help---
240 Allows the ibm_acpi driver to handle docking station events.
241 This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI. It will
242 allow locking and removing the laptop from the docking station,
243 but will not properly connect PCI devices.
244
245 If you are not sure, say N here.
246
247config ACPI_IBM_BAY
248 bool "Legacy Removable Bay Support"
249 depends on ACPI_IBM
250 default y
251 ---help---
252 Allows the ibm_acpi driver to handle removable bays. It will allow
253 disabling the device in the bay, and also generate notifications when
254 the bay lever is ejected or inserted.
255
256 If you are not sure, say Y here.
257
258config ACPI_TOSHIBA 221config ACPI_TOSHIBA
259 tristate "Toshiba Laptop Extras" 222 tristate "Toshiba Laptop Extras"
260 depends on X86 223 depends on X86
@@ -388,11 +351,10 @@ config ACPI_HOTPLUG_MEMORY
388 351
389config ACPI_SBS 352config ACPI_SBS
390 tristate "Smart Battery System (EXPERIMENTAL)" 353 tristate "Smart Battery System (EXPERIMENTAL)"
391 depends on X86 && I2C 354 depends on X86
392 depends on EXPERIMENTAL 355 depends on EXPERIMENTAL
393 help 356 help
394 This driver adds support for the Smart Battery System. 357 This driver adds support for the Smart Battery System.
395 Depends on I2C (Device Drivers ---> I2C support)
396 A "Smart Battery" is quite old and quite rare compared 358 A "Smart Battery" is quite old and quite rare compared
397 to today's ACPI "Control Method" battery. 359 to today's ACPI "Control Method" battery.
398 360
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 5956e9f64a8b..d4336f1730e9 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -1,6 +1,6 @@
1# 1#
2# Makefile for the Linux ACPI interpreter 2# Makefile for the Linux ACPI interpreter
3# 3#
4 4
5export ACPI_CFLAGS 5export ACPI_CFLAGS
6 6
@@ -32,16 +32,17 @@ obj-y += osl.o utils.o \
32processor-objs += processor_core.o processor_throttling.o \ 32processor-objs += processor_core.o processor_throttling.o \
33 processor_idle.o processor_thermal.o 33 processor_idle.o processor_thermal.o
34ifdef CONFIG_CPU_FREQ 34ifdef CONFIG_CPU_FREQ
35processor-objs += processor_perflib.o 35processor-objs += processor_perflib.o
36endif 36endif
37 37
38obj-y += sleep/ 38obj-y += sleep/
39obj-y += bus.o glue.o 39obj-y += bus.o glue.o
40obj-y += scan.o 40obj-y += scan.o
41# Keep EC driver first. Initialization of others depend on it.
42obj-$(CONFIG_ACPI_EC) += ec.o
41obj-$(CONFIG_ACPI_AC) += ac.o 43obj-$(CONFIG_ACPI_AC) += ac.o
42obj-$(CONFIG_ACPI_BATTERY) += battery.o 44obj-$(CONFIG_ACPI_BATTERY) += battery.o
43obj-$(CONFIG_ACPI_BUTTON) += button.o 45obj-$(CONFIG_ACPI_BUTTON) += button.o
44obj-$(CONFIG_ACPI_EC) += ec.o
45obj-$(CONFIG_ACPI_FAN) += fan.o 46obj-$(CONFIG_ACPI_FAN) += fan.o
46obj-$(CONFIG_ACPI_DOCK) += dock.o 47obj-$(CONFIG_ACPI_DOCK) += dock.o
47obj-$(CONFIG_ACPI_BAY) += bay.o 48obj-$(CONFIG_ACPI_BAY) += bay.o
@@ -55,8 +56,7 @@ obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
55obj-$(CONFIG_ACPI_DEBUG) += debug.o 56obj-$(CONFIG_ACPI_DEBUG) += debug.o
56obj-$(CONFIG_ACPI_NUMA) += numa.o 57obj-$(CONFIG_ACPI_NUMA) += numa.o
57obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o 58obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
58obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
59obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 59obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
60obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o 60obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
61obj-y += cm_sbs.o 61obj-y += cm_sbs.o
62obj-$(CONFIG_ACPI_SBS) += i2c_ec.o sbs.o 62obj-$(CONFIG_ACPI_SBS) += sbs.o
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index c26172671fd8..e65628a03085 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -44,11 +44,6 @@ MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
44MODULE_DESCRIPTION("Hotplug Mem Driver"); 44MODULE_DESCRIPTION("Hotplug Mem Driver");
45MODULE_LICENSE("GPL"); 45MODULE_LICENSE("GPL");
46 46
47/* ACPI _STA method values */
48#define ACPI_MEMORY_STA_PRESENT (0x00000001UL)
49#define ACPI_MEMORY_STA_ENABLED (0x00000002UL)
50#define ACPI_MEMORY_STA_FUNCTIONAL (0x00000008UL)
51
52/* Memory Device States */ 47/* Memory Device States */
53#define MEMORY_INVALID_STATE 0 48#define MEMORY_INVALID_STATE 0
54#define MEMORY_POWER_ON_STATE 1 49#define MEMORY_POWER_ON_STATE 1
@@ -204,9 +199,9 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
204 * Check for device status. Device should be 199 * Check for device status. Device should be
205 * present/enabled/functioning. 200 * present/enabled/functioning.
206 */ 201 */
207 if (!((current_status & ACPI_MEMORY_STA_PRESENT) 202 if (!((current_status & ACPI_STA_DEVICE_PRESENT)
208 && (current_status & ACPI_MEMORY_STA_ENABLED) 203 && (current_status & ACPI_STA_DEVICE_ENABLED)
209 && (current_status & ACPI_MEMORY_STA_FUNCTIONAL))) 204 && (current_status & ACPI_STA_DEVICE_FUNCTIONING)))
210 return -ENODEV; 205 return -ENODEV;
211 206
212 return 0; 207 return 0;
@@ -286,7 +281,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
286 return -ENODEV; 281 return -ENODEV;
287 282
288 /* Check for device status. Device should be disabled */ 283 /* Check for device status. Device should be disabled */
289 if (current_status & ACPI_MEMORY_STA_ENABLED) 284 if (current_status & ACPI_STA_DEVICE_ENABLED)
290 return -EINVAL; 285 return -EINVAL;
291 286
292 return 0; 287 return 0;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index dd49ea0d0ed3..e5084ececb6f 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -103,7 +103,9 @@ int acpi_bus_get_status(struct acpi_device *device)
103 else if (device->parent) 103 else if (device->parent)
104 device->status = device->parent->status; 104 device->status = device->parent->status;
105 else 105 else
106 STRUCT_TO_INT(device->status) = 0x0F; 106 STRUCT_TO_INT(device->status) =
107 ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
108 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
107 109
108 if (device->status.functional && !device->status.present) { 110 if (device->status.functional && !device->status.present) {
109 printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: " 111 printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 0930d9413dfa..0dd3bf7c0ed1 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -49,8 +49,6 @@ MODULE_AUTHOR("Anil S Keshavamurthy");
49MODULE_DESCRIPTION("ACPI container driver"); 49MODULE_DESCRIPTION("ACPI container driver");
50MODULE_LICENSE("GPL"); 50MODULE_LICENSE("GPL");
51 51
52#define ACPI_STA_PRESENT (0x00000001)
53
54static int acpi_container_add(struct acpi_device *device); 52static int acpi_container_add(struct acpi_device *device);
55static int acpi_container_remove(struct acpi_device *device, int type); 53static int acpi_container_remove(struct acpi_device *device, int type);
56 54
@@ -75,13 +73,13 @@ static int is_device_present(acpi_handle handle)
75 73
76 status = acpi_get_handle(handle, "_STA", &temp); 74 status = acpi_get_handle(handle, "_STA", &temp);
77 if (ACPI_FAILURE(status)) 75 if (ACPI_FAILURE(status))
78 return 1; /* _STA not found, assmue device present */ 76 return 1; /* _STA not found, assume device present */
79 77
80 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); 78 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
81 if (ACPI_FAILURE(status)) 79 if (ACPI_FAILURE(status))
82 return 0; /* Firmware error */ 80 return 0; /* Firmware error */
83 81
84 return ((sta & ACPI_STA_PRESENT) == ACPI_STA_PRESENT); 82 return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
85} 83}
86 84
87/*******************************************************************/ 85/*******************************************************************/
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 54a697f9aa18..4546bf873aea 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -29,6 +29,7 @@
29#include <linux/notifier.h> 29#include <linux/notifier.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/jiffies.h> 31#include <linux/jiffies.h>
32#include <linux/stddef.h>
32#include <acpi/acpi_bus.h> 33#include <acpi/acpi_bus.h>
33#include <acpi/acpi_drivers.h> 34#include <acpi/acpi_drivers.h>
34 35
@@ -667,6 +668,23 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
667} 668}
668DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); 669DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
669 670
671/*
672 * show_dock_uid - read method for "uid" file in sysfs
673 */
674static ssize_t show_dock_uid(struct device *dev,
675 struct device_attribute *attr, char *buf)
676{
677 unsigned long lbuf;
678 acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf);
679 if(ACPI_FAILURE(status)) {
680 return 0;
681 }
682 return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
683}
684DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
685
686
687
670/** 688/**
671 * dock_add - add a new dock station 689 * dock_add - add a new dock station
672 * @handle: the dock station handle 690 * @handle: the dock station handle
@@ -715,6 +733,13 @@ static int dock_add(acpi_handle handle)
715 kfree(dock_station); 733 kfree(dock_station);
716 return ret; 734 return ret;
717 } 735 }
736 ret = device_create_file(&dock_device.dev, &dev_attr_uid);
737 if (ret) {
738 printk("Error %d adding sysfs file\n", ret);
739 platform_device_unregister(&dock_device);
740 kfree(dock_station);
741 return ret;
742 }
718 743
719 /* Find dependent devices */ 744 /* Find dependent devices */
720 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 745 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index a802962ff2b4..e08cf98f504f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $) 2 * ec.c - ACPI Embedded Controller Driver (v2.0)
3 * 3 *
4 * Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
5 * Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
4 * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> 6 * Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
5 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 7 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 8 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -91,9 +93,9 @@ static struct acpi_driver acpi_ec_driver = {
91}; 93};
92 94
93/* If we find an EC via the ECDT, we need to keep a ptr to its context */ 95/* If we find an EC via the ECDT, we need to keep a ptr to its context */
96/* External interfaces use first EC only, so remember */
94static struct acpi_ec { 97static struct acpi_ec {
95 acpi_handle handle; 98 acpi_handle handle;
96 unsigned long uid;
97 unsigned long gpe; 99 unsigned long gpe;
98 unsigned long command_addr; 100 unsigned long command_addr;
99 unsigned long data_addr; 101 unsigned long data_addr;
@@ -101,12 +103,8 @@ static struct acpi_ec {
101 struct mutex lock; 103 struct mutex lock;
102 atomic_t query_pending; 104 atomic_t query_pending;
103 atomic_t event_count; 105 atomic_t event_count;
104 atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
105 wait_queue_head_t wait; 106 wait_queue_head_t wait;
106} *ec_ecdt; 107} *boot_ec, *first_ec;
107
108/* External interfaces use first EC only, so remember */
109static struct acpi_device *first_ec;
110 108
111/* -------------------------------------------------------------------------- 109/* --------------------------------------------------------------------------
112 Transaction Management 110 Transaction Management
@@ -173,56 +171,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
173 return -ETIME; 171 return -ETIME;
174} 172}
175 173
176#ifdef ACPI_FUTURE_USAGE
177/*
178 * Note: samsung nv5000 doesn't work with ec burst mode.
179 * http://bugzilla.kernel.org/show_bug.cgi?id=4980
180 */
181int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
182{
183 u8 tmp = 0;
184 u8 status = 0;
185
186 status = acpi_ec_read_status(ec);
187 if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
188 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
189 if (status)
190 goto end;
191 acpi_ec_write_cmd(ec, ACPI_EC_BURST_ENABLE);
192 status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
193 tmp = acpi_ec_read_data(ec);
194 if (tmp != 0x90) { /* Burst ACK byte */
195 return -EINVAL;
196 }
197 }
198
199 atomic_set(&ec->leaving_burst, 0);
200 return 0;
201 end:
202 ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode"));
203 return -1;
204}
205
206int acpi_ec_leave_burst_mode(struct acpi_ec *ec)
207{
208 u8 status = 0;
209
210 status = acpi_ec_read_status(ec);
211 if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) {
212 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
213 if (status)
214 goto end;
215 acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE);
216 acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
217 }
218 atomic_set(&ec->leaving_burst, 1);
219 return 0;
220 end:
221 ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode"));
222 return -1;
223}
224#endif /* ACPI_FUTURE_USAGE */
225
226static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, 174static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
227 const u8 * wdata, unsigned wdata_len, 175 const u8 * wdata, unsigned wdata_len,
228 u8 * rdata, unsigned rdata_len) 176 u8 * rdata, unsigned rdata_len)
@@ -312,6 +260,21 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
312 return status; 260 return status;
313} 261}
314 262
263/*
264 * Note: samsung nv5000 doesn't work with ec burst mode.
265 * http://bugzilla.kernel.org/show_bug.cgi?id=4980
266 */
267int acpi_ec_burst_enable(struct acpi_ec *ec)
268{
269 u8 d;
270 return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1);
271}
272
273int acpi_ec_burst_disable(struct acpi_ec *ec)
274{
275 return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0);
276}
277
315static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) 278static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
316{ 279{
317 int result; 280 int result;
@@ -333,18 +296,33 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
333/* 296/*
334 * Externally callable EC access functions. For now, assume 1 EC only 297 * Externally callable EC access functions. For now, assume 1 EC only
335 */ 298 */
299int ec_burst_enable(void)
300{
301 if (!first_ec)
302 return -ENODEV;
303 return acpi_ec_burst_enable(first_ec);
304}
305
306EXPORT_SYMBOL(ec_burst_enable);
307
308int ec_burst_disable(void)
309{
310 if (!first_ec)
311 return -ENODEV;
312 return acpi_ec_burst_disable(first_ec);
313}
314
315EXPORT_SYMBOL(ec_burst_disable);
316
336int ec_read(u8 addr, u8 * val) 317int ec_read(u8 addr, u8 * val)
337{ 318{
338 struct acpi_ec *ec;
339 int err; 319 int err;
340 u8 temp_data; 320 u8 temp_data;
341 321
342 if (!first_ec) 322 if (!first_ec)
343 return -ENODEV; 323 return -ENODEV;
344 324
345 ec = acpi_driver_data(first_ec); 325 err = acpi_ec_read(first_ec, addr, &temp_data);
346
347 err = acpi_ec_read(ec, addr, &temp_data);
348 326
349 if (!err) { 327 if (!err) {
350 *val = temp_data; 328 *val = temp_data;
@@ -357,15 +335,12 @@ EXPORT_SYMBOL(ec_read);
357 335
358int ec_write(u8 addr, u8 val) 336int ec_write(u8 addr, u8 val)
359{ 337{
360 struct acpi_ec *ec;
361 int err; 338 int err;
362 339
363 if (!first_ec) 340 if (!first_ec)
364 return -ENODEV; 341 return -ENODEV;
365 342
366 ec = acpi_driver_data(first_ec); 343 err = acpi_ec_write(first_ec, addr, val);
367
368 err = acpi_ec_write(ec, addr, val);
369 344
370 return err; 345 return err;
371} 346}
@@ -376,14 +351,10 @@ int ec_transaction(u8 command,
376 const u8 * wdata, unsigned wdata_len, 351 const u8 * wdata, unsigned wdata_len,
377 u8 * rdata, unsigned rdata_len) 352 u8 * rdata, unsigned rdata_len)
378{ 353{
379 struct acpi_ec *ec;
380
381 if (!first_ec) 354 if (!first_ec)
382 return -ENODEV; 355 return -ENODEV;
383 356
384 ec = acpi_driver_data(first_ec); 357 return acpi_ec_transaction(first_ec, command, wdata,
385
386 return acpi_ec_transaction(ec, command, wdata,
387 wdata_len, rdata, rdata_len); 358 wdata_len, rdata, rdata_len);
388} 359}
389 360
@@ -420,7 +391,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
420 391
421static void acpi_ec_gpe_query(void *ec_cxt) 392static void acpi_ec_gpe_query(void *ec_cxt)
422{ 393{
423 struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; 394 struct acpi_ec *ec = ec_cxt;
424 u8 value = 0; 395 u8 value = 0;
425 char object_name[8]; 396 char object_name[8];
426 397
@@ -438,8 +409,9 @@ static u32 acpi_ec_gpe_handler(void *data)
438{ 409{
439 acpi_status status = AE_OK; 410 acpi_status status = AE_OK;
440 u8 value; 411 u8 value;
441 struct acpi_ec *ec = (struct acpi_ec *)data; 412 struct acpi_ec *ec = data;
442 atomic_inc(&ec->event_count); 413 atomic_inc(&ec->event_count);
414
443 if (acpi_ec_mode == EC_INTR) { 415 if (acpi_ec_mode == EC_INTR) {
444 wake_up(&ec->wait); 416 wake_up(&ec->wait);
445 } 417 }
@@ -482,7 +454,7 @@ acpi_ec_space_handler(u32 function,
482 void *handler_context, void *region_context) 454 void *handler_context, void *region_context)
483{ 455{
484 int result = 0; 456 int result = 0;
485 struct acpi_ec *ec = NULL; 457 struct acpi_ec *ec = handler_context;
486 u64 temp = *value; 458 u64 temp = *value;
487 acpi_integer f_v = 0; 459 acpi_integer f_v = 0;
488 int i = 0; 460 int i = 0;
@@ -494,8 +466,6 @@ acpi_ec_space_handler(u32 function,
494 return AE_BAD_PARAMETER; 466 return AE_BAD_PARAMETER;
495 } 467 }
496 468
497 ec = (struct acpi_ec *)handler_context;
498
499 next_byte: 469 next_byte:
500 switch (function) { 470 switch (function) {
501 case ACPI_READ: 471 case ACPI_READ:
@@ -551,18 +521,16 @@ static struct proc_dir_entry *acpi_ec_dir;
551 521
552static int acpi_ec_read_info(struct seq_file *seq, void *offset) 522static int acpi_ec_read_info(struct seq_file *seq, void *offset)
553{ 523{
554 struct acpi_ec *ec = (struct acpi_ec *)seq->private; 524 struct acpi_ec *ec = seq->private;
555 525
556 if (!ec) 526 if (!ec)
557 goto end; 527 goto end;
558 528
559 seq_printf(seq, "gpe: 0x%02x\n", (u32) ec->gpe); 529 seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe);
560 seq_printf(seq, "ports: 0x%02x, 0x%02x\n", 530 seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n",
561 (u32) ec->command_addr, (u32) ec->data_addr); 531 (unsigned)ec->command_addr, (unsigned)ec->data_addr);
562 seq_printf(seq, "use global lock: %s\n", 532 seq_printf(seq, "use global lock:\t%s\n",
563 ec->global_lock ? "yes" : "no"); 533 ec->global_lock ? "yes" : "no");
564 acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
565
566 end: 534 end:
567 return 0; 535 return 0;
568} 536}
@@ -619,154 +587,122 @@ static int acpi_ec_remove_fs(struct acpi_device *device)
619/* -------------------------------------------------------------------------- 587/* --------------------------------------------------------------------------
620 Driver Interface 588 Driver Interface
621 -------------------------------------------------------------------------- */ 589 -------------------------------------------------------------------------- */
590static acpi_status
591ec_parse_io_ports(struct acpi_resource *resource, void *context);
592
593static acpi_status
594ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval);
595
596static struct acpi_ec *make_acpi_ec(void)
597{
598 struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
599 if (!ec)
600 return NULL;
601
602 atomic_set(&ec->query_pending, 1);
603 atomic_set(&ec->event_count, 1);
604 mutex_init(&ec->lock);
605 init_waitqueue_head(&ec->wait);
606
607 return ec;
608}
622 609
623static int acpi_ec_add(struct acpi_device *device) 610static int acpi_ec_add(struct acpi_device *device)
624{ 611{
625 int result = 0;
626 acpi_status status = AE_OK; 612 acpi_status status = AE_OK;
627 struct acpi_ec *ec = NULL; 613 struct acpi_ec *ec = NULL;
628 614
629 if (!device) 615 if (!device)
630 return -EINVAL; 616 return -EINVAL;
631 617
632 ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
633 if (!ec)
634 return -ENOMEM;
635
636 ec->handle = device->handle;
637 ec->uid = -1;
638 mutex_init(&ec->lock);
639 atomic_set(&ec->query_pending, 0);
640 atomic_set(&ec->event_count, 1);
641 if (acpi_ec_mode == EC_INTR) {
642 atomic_set(&ec->leaving_burst, 1);
643 init_waitqueue_head(&ec->wait);
644 }
645 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); 618 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
646 strcpy(acpi_device_class(device), ACPI_EC_CLASS); 619 strcpy(acpi_device_class(device), ACPI_EC_CLASS);
647 acpi_driver_data(device) = ec;
648
649 /* Use the global lock for all EC transactions? */
650 acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
651
652 /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
653 http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
654 if (ec_ecdt) {
655 acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
656 ACPI_ADR_SPACE_EC,
657 &acpi_ec_space_handler);
658 620
659 acpi_remove_gpe_handler(NULL, ec_ecdt->gpe, 621 ec = make_acpi_ec();
660 &acpi_ec_gpe_handler); 622 if (!ec)
623 return -ENOMEM;
661 624
662 kfree(ec_ecdt); 625 status = ec_parse_device(device->handle, 0, ec, NULL);
626 if (status != AE_CTRL_TERMINATE) {
627 kfree(ec);
628 return -EINVAL;
663 } 629 }
664 630
665 /* Get GPE bit assignment (EC events). */ 631 /* Check if we found the boot EC */
666 /* TODO: Add support for _GPE returning a package */ 632 if (boot_ec) {
667 status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe); 633 if (boot_ec->gpe == ec->gpe) {
668 if (ACPI_FAILURE(status)) { 634 /* We might have incorrect info for GL at boot time */
669 ACPI_EXCEPTION((AE_INFO, status, 635 mutex_lock(&boot_ec->lock);
670 "Obtaining GPE bit assignment")); 636 boot_ec->global_lock = ec->global_lock;
671 result = -ENODEV; 637 mutex_unlock(&boot_ec->lock);
672 goto end; 638 kfree(ec);
673 } 639 ec = boot_ec;
640 }
641 } else
642 first_ec = ec;
643 ec->handle = device->handle;
644 acpi_driver_data(device) = ec;
674 645
675 result = acpi_ec_add_fs(device); 646 acpi_ec_add_fs(device);
676 if (result)
677 goto end;
678 647
679 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.", 648 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
680 acpi_device_name(device), acpi_device_bid(device), 649 acpi_device_name(device), acpi_device_bid(device),
681 (u32) ec->gpe)); 650 (u32) ec->gpe));
682 651
683 if (!first_ec) 652 return 0;
684 first_ec = device;
685
686 end:
687 if (result)
688 kfree(ec);
689
690 return result;
691} 653}
692 654
693static int acpi_ec_remove(struct acpi_device *device, int type) 655static int acpi_ec_remove(struct acpi_device *device, int type)
694{ 656{
695 struct acpi_ec *ec = NULL; 657 struct acpi_ec *ec;
696 658
697 if (!device) 659 if (!device)
698 return -EINVAL; 660 return -EINVAL;
699 661
700 ec = acpi_driver_data(device); 662 ec = acpi_driver_data(device);
701
702 acpi_ec_remove_fs(device); 663 acpi_ec_remove_fs(device);
664 acpi_driver_data(device) = NULL;
665 if (ec == first_ec)
666 first_ec = NULL;
703 667
704 kfree(ec); 668 /* Don't touch boot EC */
705 669 if (boot_ec != ec)
670 kfree(ec);
706 return 0; 671 return 0;
707} 672}
708 673
709static acpi_status 674static acpi_status
710acpi_ec_io_ports(struct acpi_resource *resource, void *context) 675ec_parse_io_ports(struct acpi_resource *resource, void *context)
711{ 676{
712 struct acpi_ec *ec = (struct acpi_ec *)context; 677 struct acpi_ec *ec = context;
713 678
714 if (resource->type != ACPI_RESOURCE_TYPE_IO) { 679 if (resource->type != ACPI_RESOURCE_TYPE_IO)
715 return AE_OK; 680 return AE_OK;
716 }
717 681
718 /* 682 /*
719 * The first address region returned is the data port, and 683 * The first address region returned is the data port, and
720 * the second address region returned is the status/command 684 * the second address region returned is the status/command
721 * port. 685 * port.
722 */ 686 */
723 if (ec->data_addr == 0) { 687 if (ec->data_addr == 0)
724 ec->data_addr = resource->data.io.minimum; 688 ec->data_addr = resource->data.io.minimum;
725 } else if (ec->command_addr == 0) { 689 else if (ec->command_addr == 0)
726 ec->command_addr = resource->data.io.minimum; 690 ec->command_addr = resource->data.io.minimum;
727 } else { 691 else
728 return AE_CTRL_TERMINATE; 692 return AE_CTRL_TERMINATE;
729 }
730 693
731 return AE_OK; 694 return AE_OK;
732} 695}
733 696
734static int acpi_ec_start(struct acpi_device *device) 697static int ec_install_handlers(struct acpi_ec *ec)
735{ 698{
736 acpi_status status = AE_OK; 699 acpi_status status;
737 struct acpi_ec *ec = NULL;
738
739 if (!device)
740 return -EINVAL;
741
742 ec = acpi_driver_data(device);
743
744 if (!ec)
745 return -EINVAL;
746
747 /*
748 * Get I/O port addresses. Convert to GAS format.
749 */
750 status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS,
751 acpi_ec_io_ports, ec);
752 if (ACPI_FAILURE(status) || ec->command_addr == 0) {
753 ACPI_EXCEPTION((AE_INFO, status,
754 "Error getting I/O port addresses"));
755 return -ENODEV;
756 }
757
758 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
759 ec->gpe, ec->command_addr, ec->data_addr));
760
761 /*
762 * Install GPE handler
763 */
764 status = acpi_install_gpe_handler(NULL, ec->gpe, 700 status = acpi_install_gpe_handler(NULL, ec->gpe,
765 ACPI_GPE_EDGE_TRIGGERED, 701 ACPI_GPE_EDGE_TRIGGERED,
766 &acpi_ec_gpe_handler, ec); 702 &acpi_ec_gpe_handler, ec);
767 if (ACPI_FAILURE(status)) { 703 if (ACPI_FAILURE(status))
768 return -ENODEV; 704 return -ENODEV;
769 } 705
770 acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); 706 acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
771 acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); 707 acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
772 708
@@ -779,18 +715,49 @@ static int acpi_ec_start(struct acpi_device *device)
779 return -ENODEV; 715 return -ENODEV;
780 } 716 }
781 717
782 return AE_OK; 718 /* EC is fully operational, allow queries */
719 atomic_set(&ec->query_pending, 0);
720
721 return 0;
722}
723
724static int acpi_ec_start(struct acpi_device *device)
725{
726 struct acpi_ec *ec;
727
728 if (!device)
729 return -EINVAL;
730
731 ec = acpi_driver_data(device);
732
733 if (!ec)
734 return -EINVAL;
735
736 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
737 ec->gpe, ec->command_addr, ec->data_addr));
738
739 /* Boot EC is already working */
740 if (ec == boot_ec)
741 return 0;
742
743 return ec_install_handlers(ec);
783} 744}
784 745
785static int acpi_ec_stop(struct acpi_device *device, int type) 746static int acpi_ec_stop(struct acpi_device *device, int type)
786{ 747{
787 acpi_status status = AE_OK; 748 acpi_status status;
788 struct acpi_ec *ec = NULL; 749 struct acpi_ec *ec;
789 750
790 if (!device) 751 if (!device)
791 return -EINVAL; 752 return -EINVAL;
792 753
793 ec = acpi_driver_data(device); 754 ec = acpi_driver_data(device);
755 if (!ec)
756 return -EINVAL;
757
758 /* Don't touch boot EC */
759 if (ec == boot_ec)
760 return 0;
794 761
795 status = acpi_remove_address_space_handler(ec->handle, 762 status = acpi_remove_address_space_handler(ec->handle,
796 ACPI_ADR_SPACE_EC, 763 ACPI_ADR_SPACE_EC,
@@ -805,164 +772,67 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
805 return 0; 772 return 0;
806} 773}
807 774
808static acpi_status __init 775static acpi_status
809acpi_fake_ecdt_callback(acpi_handle handle, 776ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
810 u32 Level, void *context, void **retval)
811{ 777{
812 acpi_status status; 778 acpi_status status;
813 779
814 mutex_init(&ec_ecdt->lock); 780 struct acpi_ec *ec = context;
815 atomic_set(&ec_ecdt->event_count, 1);
816 if (acpi_ec_mode == EC_INTR) {
817 init_waitqueue_head(&ec_ecdt->wait);
818 }
819 status = acpi_walk_resources(handle, METHOD_NAME__CRS, 781 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
820 acpi_ec_io_ports, ec_ecdt); 782 ec_parse_io_ports, ec);
821 if (ACPI_FAILURE(status)) 783 if (ACPI_FAILURE(status))
822 return status; 784 return status;
823 785
824 ec_ecdt->uid = -1; 786 /* Get GPE bit assignment (EC events). */
825 acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); 787 /* TODO: Add support for _GPE returning a package */
826 788 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
827 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe);
828 if (ACPI_FAILURE(status)) 789 if (ACPI_FAILURE(status))
829 return status; 790 return status;
830 ec_ecdt->global_lock = TRUE;
831 ec_ecdt->handle = handle;
832
833 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
834 ec_ecdt->gpe, ec_ecdt->command_addr,
835 ec_ecdt->data_addr));
836 791
837 return AE_CTRL_TERMINATE; 792 /* Use the global lock for all EC transactions? */
838} 793 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
839
840/*
841 * Some BIOS (such as some from Gateway laptops) access EC region very early
842 * such as in BAT0._INI or EC._INI before an EC device is found and
843 * do not provide an ECDT. According to ACPI spec, ECDT isn't mandatorily
844 * required, but if EC regison is accessed early, it is required.
845 * The routine tries to workaround the BIOS bug by pre-scan EC device
846 * It assumes that _CRS, _HID, _GPE, _UID methods of EC don't touch any
847 * op region (since _REG isn't invoked yet). The assumption is true for
848 * all systems found.
849 */
850static int __init acpi_ec_fake_ecdt(void)
851{
852 acpi_status status;
853 int ret = 0;
854 794
855 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Try to make an fake ECDT")); 795 ec->handle = handle;
856 796
857 ec_ecdt = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); 797 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
858 if (!ec_ecdt) { 798 ec->gpe, ec->command_addr, ec->data_addr));
859 ret = -ENOMEM;
860 goto error;
861 }
862 799
863 status = acpi_get_devices(ACPI_EC_HID, 800 return AE_CTRL_TERMINATE;
864 acpi_fake_ecdt_callback, NULL, NULL);
865 if (ACPI_FAILURE(status)) {
866 kfree(ec_ecdt);
867 ec_ecdt = NULL;
868 ret = -ENODEV;
869 ACPI_EXCEPTION((AE_INFO, status, "Can't make an fake ECDT"));
870 goto error;
871 }
872 return 0;
873 error:
874 return ret;
875} 801}
876 802
877static int __init acpi_ec_get_real_ecdt(void) 803int __init acpi_ec_ecdt_probe(void)
878{ 804{
805 int ret;
879 acpi_status status; 806 acpi_status status;
880 struct acpi_table_ecdt *ecdt_ptr; 807 struct acpi_table_ecdt *ecdt_ptr;
881 808
882 status = acpi_get_table(ACPI_SIG_ECDT, 1, 809 boot_ec = make_acpi_ec();
883 (struct acpi_table_header **)&ecdt_ptr); 810 if (!boot_ec)
884 if (ACPI_FAILURE(status)) 811 return -ENOMEM;
885 return -ENODEV;
886
887 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
888
889 /* 812 /*
890 * Generate a temporary ec context to use until the namespace is scanned 813 * Generate a boot ec context
891 */ 814 */
892 ec_ecdt = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
893 if (!ec_ecdt)
894 return -ENOMEM;
895 815
896 mutex_init(&ec_ecdt->lock); 816 status = acpi_get_table(ACPI_SIG_ECDT, 1,
897 atomic_set(&ec_ecdt->event_count, 1); 817 (struct acpi_table_header **)&ecdt_ptr);
898 if (acpi_ec_mode == EC_INTR) { 818 if (ACPI_FAILURE(status))
899 init_waitqueue_head(&ec_ecdt->wait);
900 }
901 ec_ecdt->command_addr = ecdt_ptr->control.address;
902 ec_ecdt->data_addr = ecdt_ptr->data.address;
903 ec_ecdt->gpe = ecdt_ptr->gpe;
904 /* use the GL just to be safe */
905 ec_ecdt->global_lock = TRUE;
906 ec_ecdt->uid = ecdt_ptr->uid;
907
908 status = acpi_get_handle(NULL, ecdt_ptr->id, &ec_ecdt->handle);
909 if (ACPI_FAILURE(status)) {
910 goto error; 819 goto error;
911 }
912
913 return 0;
914 error:
915 ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
916 kfree(ec_ecdt);
917 ec_ecdt = NULL;
918 820
919 return -ENODEV; 821 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
920}
921
922static int __initdata acpi_fake_ecdt_enabled;
923int __init acpi_ec_ecdt_probe(void)
924{
925 acpi_status status;
926 int ret;
927 822
928 ret = acpi_ec_get_real_ecdt(); 823 boot_ec->command_addr = ecdt_ptr->control.address;
929 /* Try to make a fake ECDT */ 824 boot_ec->data_addr = ecdt_ptr->data.address;
930 if (ret && acpi_fake_ecdt_enabled) { 825 boot_ec->gpe = ecdt_ptr->gpe;
931 ret = acpi_ec_fake_ecdt(); 826 boot_ec->handle = ACPI_ROOT_OBJECT;
932 }
933 827
934 if (ret) 828 ret = ec_install_handlers(boot_ec);
829 if (!ret) {
830 first_ec = boot_ec;
935 return 0; 831 return 0;
936
937 /*
938 * Install GPE handler
939 */
940 status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe,
941 ACPI_GPE_EDGE_TRIGGERED,
942 &acpi_ec_gpe_handler, ec_ecdt);
943 if (ACPI_FAILURE(status)) {
944 goto error;
945 } 832 }
946 acpi_set_gpe_type(NULL, ec_ecdt->gpe, ACPI_GPE_TYPE_RUNTIME);
947 acpi_enable_gpe(NULL, ec_ecdt->gpe, ACPI_NOT_ISR);
948
949 status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
950 ACPI_ADR_SPACE_EC,
951 &acpi_ec_space_handler,
952 &acpi_ec_space_setup,
953 ec_ecdt);
954 if (ACPI_FAILURE(status)) {
955 acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
956 &acpi_ec_gpe_handler);
957 goto error;
958 }
959
960 return 0;
961
962 error: 833 error:
963 ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT")); 834 kfree(boot_ec);
964 kfree(ec_ecdt); 835 boot_ec = NULL;
965 ec_ecdt = NULL;
966 836
967 return -ENODEV; 837 return -ENODEV;
968} 838}
@@ -1003,13 +873,6 @@ static void __exit acpi_ec_exit(void)
1003} 873}
1004#endif /* 0 */ 874#endif /* 0 */
1005 875
1006static int __init acpi_fake_ecdt_setup(char *str)
1007{
1008 acpi_fake_ecdt_enabled = 1;
1009 return 1;
1010}
1011
1012__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
1013static int __init acpi_ec_set_intr_mode(char *str) 876static int __init acpi_ec_set_intr_mode(char *str)
1014{ 877{
1015 int intr; 878 int intr;
@@ -1017,12 +880,8 @@ static int __init acpi_ec_set_intr_mode(char *str)
1017 if (!get_option(&str, &intr)) 880 if (!get_option(&str, &intr))
1018 return 0; 881 return 0;
1019 882
1020 if (intr) { 883 acpi_ec_mode = (intr) ? EC_INTR : EC_POLL;
1021 acpi_ec_mode = EC_INTR; 884
1022 } else {
1023 acpi_ec_mode = EC_POLL;
1024 }
1025 acpi_ec_driver.ops.add = acpi_ec_add;
1026 printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling"); 885 printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling");
1027 886
1028 return 1; 887 return 1;
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
deleted file mode 100644
index acab4a481897..000000000000
--- a/drivers/acpi/i2c_ec.c
+++ /dev/null
@@ -1,403 +0,0 @@
1/*
2 * SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $)
3 *
4 * Copyright (c) 2002, 2005 Ducrot Bruno
5 * Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation version 2.
10 */
11
12#include <linux/version.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/kernel.h>
16#include <linux/stddef.h>
17#include <linux/init.h>
18#include <linux/i2c.h>
19#include <linux/acpi.h>
20#include <linux/delay.h>
21
22#include "i2c_ec.h"
23
24#define xudelay(t) udelay(t)
25#define xmsleep(t) msleep(t)
26
27#define ACPI_EC_HC_COMPONENT 0x00080000
28#define ACPI_EC_HC_CLASS "ec_hc_smbus"
29#define ACPI_EC_HC_HID "ACPI0001"
30#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
31
32#define _COMPONENT ACPI_EC_HC_COMPONENT
33
34ACPI_MODULE_NAME("i2c_ec");
35
36static int acpi_ec_hc_add(struct acpi_device *device);
37static int acpi_ec_hc_remove(struct acpi_device *device, int type);
38
39static struct acpi_driver acpi_ec_hc_driver = {
40 .name = "i2c_ec",
41 .class = ACPI_EC_HC_CLASS,
42 .ids = ACPI_EC_HC_HID,
43 .ops = {
44 .add = acpi_ec_hc_add,
45 .remove = acpi_ec_hc_remove,
46 },
47};
48
49/* Various bit mask for EC_SC (R) */
50#define OBF 0x01
51#define IBF 0x02
52#define CMD 0x08
53#define BURST 0x10
54#define SCI_EVT 0x20
55#define SMI_EVT 0x40
56
57/* Commands for EC_SC (W) */
58#define RD_EC 0x80
59#define WR_EC 0x81
60#define BE_EC 0x82
61#define BD_EC 0x83
62#define QR_EC 0x84
63
64/*
65 * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
66 */
67
68#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */
69#define ACPI_EC_SMB_STS 0x01 /* status */
70#define ACPI_EC_SMB_ADDR 0x02 /* address */
71#define ACPI_EC_SMB_CMD 0x03 /* command */
72#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */
73#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */
74#define ACPI_EC_SMB_ALRM_A 0x25 /* alarm address */
75#define ACPI_EC_SMB_ALRM_D 0x26 /* 2 bytes alarm data */
76
77#define ACPI_EC_SMB_STS_DONE 0x80
78#define ACPI_EC_SMB_STS_ALRM 0x40
79#define ACPI_EC_SMB_STS_RES 0x20
80#define ACPI_EC_SMB_STS_STATUS 0x1f
81
82#define ACPI_EC_SMB_STATUS_OK 0x00
83#define ACPI_EC_SMB_STATUS_FAIL 0x07
84#define ACPI_EC_SMB_STATUS_DNAK 0x10
85#define ACPI_EC_SMB_STATUS_DERR 0x11
86#define ACPI_EC_SMB_STATUS_CMD_DENY 0x12
87#define ACPI_EC_SMB_STATUS_UNKNOWN 0x13
88#define ACPI_EC_SMB_STATUS_ACC_DENY 0x17
89#define ACPI_EC_SMB_STATUS_TIMEOUT 0x18
90#define ACPI_EC_SMB_STATUS_NOTSUP 0x19
91#define ACPI_EC_SMB_STATUS_BUSY 0x1A
92#define ACPI_EC_SMB_STATUS_PEC 0x1F
93
94#define ACPI_EC_SMB_PRTCL_WRITE 0x00
95#define ACPI_EC_SMB_PRTCL_READ 0x01
96#define ACPI_EC_SMB_PRTCL_QUICK 0x02
97#define ACPI_EC_SMB_PRTCL_BYTE 0x04
98#define ACPI_EC_SMB_PRTCL_BYTE_DATA 0x06
99#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
100#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
101#define ACPI_EC_SMB_PRTCL_PROC_CALL 0x0c
102#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
103#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
104#define ACPI_EC_SMB_PRTCL_PEC 0x80
105
106/* Length of pre/post transaction sleep (msec) */
107#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
108#define ACPI_EC_SMB_ACCESS_SLEEP1 1
109#define ACPI_EC_SMB_ACCESS_SLEEP2 10
110
111static int acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data)
112{
113 u8 val;
114 int err;
115
116 err = ec_read(smbus->base + address, &val);
117 if (!err) {
118 *data = val;
119 }
120 xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
121 return (err);
122}
123
124static int acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data)
125{
126 int err;
127
128 err = ec_write(smbus->base + address, data);
129 return (err);
130}
131
132static int
133acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
134 char read_write, u8 command, int size,
135 union i2c_smbus_data *data)
136{
137 struct acpi_ec_smbus *smbus = adap->algo_data;
138 unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 };
139 int i;
140
141 if (read_write == I2C_SMBUS_READ) {
142 protocol = ACPI_EC_SMB_PRTCL_READ;
143 } else {
144 protocol = ACPI_EC_SMB_PRTCL_WRITE;
145 }
146 pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0;
147
148 switch (size) {
149
150 case I2C_SMBUS_QUICK:
151 protocol |= ACPI_EC_SMB_PRTCL_QUICK;
152 read_write = I2C_SMBUS_WRITE;
153 break;
154
155 case I2C_SMBUS_BYTE:
156 if (read_write == I2C_SMBUS_WRITE) {
157 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
158 }
159 protocol |= ACPI_EC_SMB_PRTCL_BYTE;
160 break;
161
162 case I2C_SMBUS_BYTE_DATA:
163 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
164 if (read_write == I2C_SMBUS_WRITE) {
165 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
166 }
167 protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA;
168 break;
169
170 case I2C_SMBUS_WORD_DATA:
171 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
172 if (read_write == I2C_SMBUS_WRITE) {
173 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
174 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1,
175 data->word >> 8);
176 }
177 protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec;
178 break;
179
180 case I2C_SMBUS_BLOCK_DATA:
181 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
182 if (read_write == I2C_SMBUS_WRITE) {
183 len = min_t(u8, data->block[0], 32);
184 acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
185 for (i = 0; i < len; i++)
186 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
187 data->block[i + 1]);
188 }
189 protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec;
190 break;
191
192 case I2C_SMBUS_I2C_BLOCK_DATA:
193 len = min_t(u8, data->block[0], 32);
194 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
195 acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
196 if (read_write == I2C_SMBUS_WRITE) {
197 for (i = 0; i < len; i++) {
198 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
199 data->block[i + 1]);
200 }
201 }
202 protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA;
203 break;
204
205 case I2C_SMBUS_PROC_CALL:
206 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
207 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
208 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8);
209 protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec;
210 read_write = I2C_SMBUS_READ;
211 break;
212
213 case I2C_SMBUS_BLOCK_PROC_CALL:
214 protocol |= pec;
215 len = min_t(u8, data->block[0], 31);
216 acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
217 acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
218 for (i = 0; i < len; i++)
219 acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
220 data->block[i + 1]);
221 protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec;
222 read_write = I2C_SMBUS_READ;
223 break;
224
225 default:
226 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "EC SMBus adapter: "
227 "Unsupported transaction %d\n", size));
228 return (-1);
229 }
230
231 acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1);
232 acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol);
233
234 acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
235
236 if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
237 xudelay(500);
238 acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
239 }
240 if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
241 xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
242 acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
243 }
244 if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
245 || (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
246 return (-1);
247 }
248
249 if (read_write == I2C_SMBUS_WRITE) {
250 return (0);
251 }
252
253 switch (size) {
254
255 case I2C_SMBUS_BYTE:
256 case I2C_SMBUS_BYTE_DATA:
257 acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte);
258 break;
259
260 case I2C_SMBUS_WORD_DATA:
261 case I2C_SMBUS_PROC_CALL:
262 acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0);
263 acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1);
264 data->word = (temp[1] << 8) | temp[0];
265 break;
266
267 case I2C_SMBUS_BLOCK_DATA:
268 case I2C_SMBUS_BLOCK_PROC_CALL:
269 len = 0;
270 acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len);
271 len = min_t(u8, len, 32);
272 case I2C_SMBUS_I2C_BLOCK_DATA:
273 for (i = 0; i < len; i++)
274 acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i,
275 data->block + i + 1);
276 data->block[0] = len;
277 break;
278 }
279
280 return (0);
281}
282
283static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
284{
285
286 return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
287 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
288 I2C_FUNC_SMBUS_BLOCK_DATA |
289 I2C_FUNC_SMBUS_PROC_CALL |
290 I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
291 I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
292}
293
294static const struct i2c_algorithm acpi_ec_smbus_algorithm = {
295 .smbus_xfer = acpi_ec_smb_access,
296 .functionality = acpi_ec_smb_func,
297};
298
299static int acpi_ec_hc_add(struct acpi_device *device)
300{
301 int status;
302 unsigned long val;
303 struct acpi_ec_hc *ec_hc;
304 struct acpi_ec_smbus *smbus;
305
306 if (!device) {
307 return -EINVAL;
308 }
309
310 ec_hc = kzalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
311 if (!ec_hc) {
312 return -ENOMEM;
313 }
314
315 smbus = kzalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
316 if (!smbus) {
317 kfree(ec_hc);
318 return -ENOMEM;
319 }
320
321 ec_hc->handle = device->handle;
322 strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME);
323 strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS);
324 acpi_driver_data(device) = ec_hc;
325
326 status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
327 if (ACPI_FAILURE(status)) {
328 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
329 kfree(ec_hc);
330 kfree(smbus);
331 return -EIO;
332 }
333
334 smbus->ec = acpi_driver_data(device->parent);
335 smbus->base = (val & 0xff00ull) >> 8;
336 smbus->alert = val & 0xffull;
337
338 smbus->adapter.owner = THIS_MODULE;
339 smbus->adapter.algo = &acpi_ec_smbus_algorithm;
340 smbus->adapter.algo_data = smbus;
341 smbus->adapter.dev.parent = &device->dev;
342
343 if (i2c_add_adapter(&smbus->adapter)) {
344 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
345 "EC SMBus adapter: Failed to register adapter\n"));
346 kfree(smbus);
347 kfree(ec_hc);
348 return -EIO;
349 }
350
351 ec_hc->smbus = smbus;
352
353 printk(KERN_INFO PREFIX "%s [%s]\n",
354 acpi_device_name(device), acpi_device_bid(device));
355
356 return AE_OK;
357}
358
359static int acpi_ec_hc_remove(struct acpi_device *device, int type)
360{
361 struct acpi_ec_hc *ec_hc;
362
363 if (!device) {
364 return -EINVAL;
365 }
366 ec_hc = acpi_driver_data(device);
367
368 i2c_del_adapter(&ec_hc->smbus->adapter);
369 kfree(ec_hc->smbus);
370 kfree(ec_hc);
371
372 return AE_OK;
373}
374
375static int __init acpi_ec_hc_init(void)
376{
377 int result;
378
379 result = acpi_bus_register_driver(&acpi_ec_hc_driver);
380 if (result < 0) {
381 return -ENODEV;
382 }
383 return 0;
384}
385
386static void __exit acpi_ec_hc_exit(void)
387{
388 acpi_bus_unregister_driver(&acpi_ec_hc_driver);
389}
390
391struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
392{
393 return acpi_driver_data(device->parent);
394}
395
396EXPORT_SYMBOL(acpi_get_ec_hc);
397
398module_init(acpi_ec_hc_init);
399module_exit(acpi_ec_hc_exit);
400
401MODULE_LICENSE("GPL");
402MODULE_AUTHOR("Ducrot Bruno");
403MODULE_DESCRIPTION("ACPI EC SMBus driver");
diff --git a/drivers/acpi/i2c_ec.h b/drivers/acpi/i2c_ec.h
deleted file mode 100644
index 7c53fb732d61..000000000000
--- a/drivers/acpi/i2c_ec.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $)
3 *
4 * Copyright (c) 2002, 2005 Ducrot Bruno
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation version 2.
9 */
10
11struct acpi_ec_smbus {
12 struct i2c_adapter adapter;
13 union acpi_ec *ec;
14 int base;
15 int alert;
16};
17
18struct acpi_ec_hc {
19 acpi_handle handle;
20 struct acpi_ec_smbus *smbus;
21};
22
23struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device);
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
deleted file mode 100644
index dc1096608f43..000000000000
--- a/drivers/acpi/ibm_acpi.c
+++ /dev/null
@@ -1,2798 +0,0 @@
1/*
2 * ibm_acpi.c - IBM ThinkPad ACPI Extras
3 *
4 *
5 * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
6 * Copyright (C) 2006 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define IBM_VERSION "0.13"
24
25/*
26 * Changelog:
27 *
28 * 2006-11-22 0.13 new maintainer
29 * changelog now lives in git commit history, and will
30 * not be updated further in-file.
31 *
32 * 2005-08-17 0.12 fix compilation on 2.6.13-rc kernels
33 * 2005-03-17 0.11 support for 600e, 770x
34 * thanks to Jamie Lentin <lentinj@dial.pipex.com>
35 * support for 770e, G41
36 * G40 and G41 don't have a thinklight
37 * temperatures no longer experimental
38 * experimental brightness control
39 * experimental volume control
40 * experimental fan enable/disable
41 * 2005-01-16 0.10 fix module loading on R30, R31
42 * 2005-01-16 0.9 support for 570, R30, R31
43 * ultrabay support on A22p, A3x
44 * limit arg for cmos, led, beep, drop experimental status
45 * more capable led control on A21e, A22p, T20-22, X20
46 * experimental temperatures and fan speed
47 * experimental embedded controller register dump
48 * mark more functions as __init, drop incorrect __exit
49 * use MODULE_VERSION
50 * thanks to Henrik Brix Andersen <brix@gentoo.org>
51 * fix parameter passing on module loading
52 * thanks to Rusty Russell <rusty@rustcorp.com.au>
53 * thanks to Jim Radford <radford@blackbean.org>
54 * 2004-11-08 0.8 fix init error case, don't return from a macro
55 * thanks to Chris Wright <chrisw@osdl.org>
56 * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20
57 * fix led control on A21e
58 * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device
59 * 2004-10-18 0.5 thinklight support on A21e, G40, R32, T20, T21, X20
60 * proc file format changed
61 * video_switch command
62 * experimental cmos control
63 * experimental led control
64 * experimental acpi sounds
65 * 2004-09-16 0.4 support for module parameters
66 * hotkey mask can be prefixed by 0x
67 * video output switching
68 * video expansion control
69 * ultrabay eject support
70 * removed lcd brightness/on/off control, didn't work
71 * 2004-08-17 0.3 support for R40
72 * lcd off, brightness control
73 * thinklight on/off
74 * 2004-08-14 0.2 support for T series, X20
75 * bluetooth enable/disable
76 * hotkey events disabled by default
77 * removed fan control, currently useless
78 * 2004-08-09 0.1 initial release, support for X series
79 */
80
81#include <linux/kernel.h>
82#include <linux/module.h>
83#include <linux/init.h>
84#include <linux/types.h>
85#include <linux/string.h>
86
87#include <linux/proc_fs.h>
88#include <linux/backlight.h>
89#include <linux/fb.h>
90#include <asm/uaccess.h>
91
92#include <linux/dmi.h>
93#include <linux/jiffies.h>
94#include <linux/workqueue.h>
95
96#include <acpi/acpi_drivers.h>
97#include <acpi/acnamesp.h>
98
99#define IBM_NAME "ibm"
100#define IBM_DESC "IBM ThinkPad ACPI Extras"
101#define IBM_FILE "ibm_acpi"
102#define IBM_URL "http://ibm-acpi.sf.net/"
103
104MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
105MODULE_DESCRIPTION(IBM_DESC);
106MODULE_VERSION(IBM_VERSION);
107MODULE_LICENSE("GPL");
108
109#define IBM_DIR IBM_NAME
110
111#define IBM_LOG IBM_FILE ": "
112#define IBM_ERR KERN_ERR IBM_LOG
113#define IBM_NOTICE KERN_NOTICE IBM_LOG
114#define IBM_INFO KERN_INFO IBM_LOG
115#define IBM_DEBUG KERN_DEBUG IBM_LOG
116
117#define IBM_MAX_ACPI_ARGS 3
118
119#define __unused __attribute__ ((unused))
120
121static int experimental;
122module_param(experimental, int, 0);
123
124static acpi_handle root_handle = NULL;
125
126#define IBM_HANDLE(object, parent, paths...) \
127 static acpi_handle object##_handle; \
128 static acpi_handle *object##_parent = &parent##_handle; \
129 static char *object##_path; \
130 static char *object##_paths[] = { paths }
131
132IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */
133 "\\_SB.PCI.ISA.EC", /* 570 */
134 "\\_SB.PCI0.ISA0.EC0", /* 600e/x, 770e, 770x */
135 "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */
136 "\\_SB.PCI0.AD4S.EC0", /* i1400, R30 */
137 "\\_SB.PCI0.ICH3.EC0", /* R31 */
138 "\\_SB.PCI0.LPC.EC", /* all others */
139 );
140
141IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */
142 "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */
143 "\\_SB.PCI0.VID0", /* 770e */
144 "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */
145 "\\_SB.PCI0.AGP.VID", /* all others */
146 ); /* R30, R31 */
147
148IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */
149
150IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */
151 "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */
152 "\\CMS", /* R40, R40e */
153 ); /* all others */
154#ifdef CONFIG_ACPI_IBM_DOCK
155IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
156 "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
157 "\\_SB.PCI0.PCI1.DOCK", /* all others */
158 "\\_SB.PCI.ISA.SLCE", /* 570 */
159 ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
160#endif
161#ifdef CONFIG_ACPI_IBM_BAY
162IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
163 "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
164 "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
165 "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
166 ); /* A21e, R30, R31 */
167
168IBM_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */
169 "_EJ0", /* all others */
170 ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
171
172IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
173 "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
174 ); /* all others */
175
176IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
177 "_EJ0", /* 770x */
178 ); /* all others */
179#endif /* CONFIG_ACPI_IBM_BAY */
180
181/* don't list other alternatives as we install a notify handler on the 570 */
182IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
183
184IBM_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */
185 "^HKEY", /* R30, R31 */
186 "HKEY", /* all others */
187 ); /* 570 */
188
189IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */
190IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */
191
192IBM_HANDLE(led, ec, "SLED", /* 570 */
193 "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
194 "LED", /* all others */
195 ); /* R30, R31 */
196
197IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */
198IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */
199IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */
200IBM_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */
201
202IBM_HANDLE(gfan, ec, "GFAN", /* 570 */
203 "\\FSPD", /* 600e/x, 770e, 770x */
204 ); /* all others */
205
206IBM_HANDLE(sfan, ec, "SFAN", /* 570 */
207 "JFNS", /* 770x-JL */
208 ); /* all others */
209
210#define IBM_HKEY_HID "IBM0068"
211#define IBM_PCI_HID "PNP0A03"
212
213enum thermal_access_mode {
214 IBMACPI_THERMAL_NONE = 0, /* No thermal support */
215 IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */
216 IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */
217 IBMACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */
218 IBMACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */
219};
220
221#define IBMACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
222struct ibm_thermal_sensors_struct {
223 s32 temp[IBMACPI_MAX_THERMAL_SENSORS];
224};
225
226/*
227 * FAN ACCESS MODES
228 *
229 * IBMACPI_FAN_RD_ACPI_GFAN:
230 * ACPI GFAN method: returns fan level
231 *
232 * see IBMACPI_FAN_WR_ACPI_SFAN
233 * EC 0x2f not available if GFAN exists
234 *
235 * IBMACPI_FAN_WR_ACPI_SFAN:
236 * ACPI SFAN method: sets fan level, 0 (stop) to 7 (max)
237 *
238 * EC 0x2f might be available *for reading*, but never for writing.
239 *
240 * IBMACPI_FAN_WR_TPEC:
241 * ThinkPad EC register 0x2f (HFSP): fan control loop mode Supported
242 * on almost all ThinkPads
243 *
244 * Fan speed changes of any sort (including those caused by the
245 * disengaged mode) are usually done slowly by the firmware as the
246 * maximum ammount of fan duty cycle change per second seems to be
247 * limited.
248 *
249 * Reading is not available if GFAN exists.
250 * Writing is not available if SFAN exists.
251 *
252 * Bits
253 * 7 automatic mode engaged;
254 * (default operation mode of the ThinkPad)
255 * fan level is ignored in this mode.
256 * 6 disengage mode (takes precedence over bit 7);
257 * not available on all thinkpads. May disable
258 * the tachometer, and speeds up fan to 100% duty-cycle,
259 * which speeds it up far above the standard RPM
260 * levels. It is not impossible that it could cause
261 * hardware damage.
262 * 5-3 unused in some models. Extra bits for fan level
263 * in others, but still useless as all values above
264 * 7 map to the same speed as level 7 in these models.
265 * 2-0 fan level (0..7 usually)
266 * 0x00 = stop
267 * 0x07 = max (set when temperatures critical)
268 * Some ThinkPads may have other levels, see
269 * IBMACPI_FAN_WR_ACPI_FANS (X31/X40/X41)
270 *
271 * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at
272 * boot. Apparently the EC does not intialize it, so unless ACPI DSDT
273 * does so, its initial value is meaningless (0x07).
274 *
275 * For firmware bugs, refer to:
276 * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
277 *
278 * ----
279 *
280 * ThinkPad EC register 0x84 (LSB), 0x85 (MSB):
281 * Main fan tachometer reading (in RPM)
282 *
283 * This register is present on all ThinkPads with a new-style EC, and
284 * it is known not to be present on the A21m/e, and T22, as there is
285 * something else in offset 0x84 according to the ACPI DSDT. Other
286 * ThinkPads from this same time period (and earlier) probably lack the
287 * tachometer as well.
288 *
289 * Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare
290 * was never fixed by IBM to report the EC firmware version string
291 * probably support the tachometer (like the early X models), so
292 * detecting it is quite hard. We need more data to know for sure.
293 *
294 * FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings
295 * might result.
296 *
297 * FIRMWARE BUG: when EC 0x2f bit 6 is set (disengaged mode), this
298 * register is not invalidated in ThinkPads that disable tachometer
299 * readings. Thus, the tachometer readings go stale.
300 *
301 * For firmware bugs, refer to:
302 * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
303 *
304 * IBMACPI_FAN_WR_ACPI_FANS:
305 * ThinkPad X31, X40, X41. Not available in the X60.
306 *
307 * FANS ACPI handle: takes three arguments: low speed, medium speed,
308 * high speed. ACPI DSDT seems to map these three speeds to levels
309 * as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH
310 * (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3")
311 *
312 * The speeds are stored on handles
313 * (FANA:FAN9), (FANC:FANB), (FANE:FAND).
314 *
315 * There are three default speed sets, acessible as handles:
316 * FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
317 *
318 * ACPI DSDT switches which set is in use depending on various
319 * factors.
320 *
321 * IBMACPI_FAN_WR_TPEC is also available and should be used to
322 * command the fan. The X31/X40/X41 seems to have 8 fan levels,
323 * but the ACPI tables just mention level 7.
324 */
325
326enum fan_status_access_mode {
327 IBMACPI_FAN_NONE = 0, /* No fan status or control */
328 IBMACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */
329 IBMACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */
330};
331
332enum fan_control_access_mode {
333 IBMACPI_FAN_WR_NONE = 0, /* No fan control */
334 IBMACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */
335 IBMACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */
336 IBMACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */
337};
338
339enum fan_control_commands {
340 IBMACPI_FAN_CMD_SPEED = 0x0001, /* speed command */
341 IBMACPI_FAN_CMD_LEVEL = 0x0002, /* level command */
342 IBMACPI_FAN_CMD_ENABLE = 0x0004, /* enable/disable cmd,
343 * and also watchdog cmd */
344};
345
346enum { /* Fan control constants */
347 fan_status_offset = 0x2f, /* EC register 0x2f */
348 fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM)
349 * 0x84 must be read before 0x85 */
350
351 IBMACPI_FAN_EC_DISENGAGED = 0x40, /* EC mode: tachometer
352 * disengaged */
353 IBMACPI_FAN_EC_AUTO = 0x80, /* EC mode: auto fan
354 * control */
355};
356
357static char *ibm_thinkpad_ec_found = NULL;
358
359struct ibm_struct {
360 char *name;
361 char param[32];
362
363 char *hid;
364 struct acpi_driver *driver;
365
366 int (*init) (void);
367 int (*read) (char *);
368 int (*write) (char *);
369 void (*exit) (void);
370
371 void (*notify) (struct ibm_struct *, u32);
372 acpi_handle *handle;
373 int type;
374 struct acpi_device *device;
375
376 int driver_registered;
377 int proc_created;
378 int init_called;
379 int notify_installed;
380
381 int experimental;
382};
383
384static struct proc_dir_entry *proc_dir = NULL;
385
386static struct backlight_device *ibm_backlight_device = NULL;
387
388#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
389#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
390#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
391
392static int acpi_evalf(acpi_handle handle,
393 void *res, char *method, char *fmt, ...)
394{
395 char *fmt0 = fmt;
396 struct acpi_object_list params;
397 union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
398 struct acpi_buffer result, *resultp;
399 union acpi_object out_obj;
400 acpi_status status;
401 va_list ap;
402 char res_type;
403 int success;
404 int quiet;
405
406 if (!*fmt) {
407 printk(IBM_ERR "acpi_evalf() called with empty format\n");
408 return 0;
409 }
410
411 if (*fmt == 'q') {
412 quiet = 1;
413 fmt++;
414 } else
415 quiet = 0;
416
417 res_type = *(fmt++);
418
419 params.count = 0;
420 params.pointer = &in_objs[0];
421
422 va_start(ap, fmt);
423 while (*fmt) {
424 char c = *(fmt++);
425 switch (c) {
426 case 'd': /* int */
427 in_objs[params.count].integer.value = va_arg(ap, int);
428 in_objs[params.count++].type = ACPI_TYPE_INTEGER;
429 break;
430 /* add more types as needed */
431 default:
432 printk(IBM_ERR "acpi_evalf() called "
433 "with invalid format character '%c'\n", c);
434 return 0;
435 }
436 }
437 va_end(ap);
438
439 if (res_type != 'v') {
440 result.length = sizeof(out_obj);
441 result.pointer = &out_obj;
442 resultp = &result;
443 } else
444 resultp = NULL;
445
446 status = acpi_evaluate_object(handle, method, &params, resultp);
447
448 switch (res_type) {
449 case 'd': /* int */
450 if (res)
451 *(int *)res = out_obj.integer.value;
452 success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
453 break;
454 case 'v': /* void */
455 success = status == AE_OK;
456 break;
457 /* add more types as needed */
458 default:
459 printk(IBM_ERR "acpi_evalf() called "
460 "with invalid format character '%c'\n", res_type);
461 return 0;
462 }
463
464 if (!success && !quiet)
465 printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
466 method, fmt0, status);
467
468 return success;
469}
470
471static void __unused acpi_print_int(acpi_handle handle, char *method)
472{
473 int i;
474
475 if (acpi_evalf(handle, &i, method, "d"))
476 printk(IBM_INFO "%s = 0x%x\n", method, i);
477 else
478 printk(IBM_ERR "error calling %s\n", method);
479}
480
481static char *next_cmd(char **cmds)
482{
483 char *start = *cmds;
484 char *end;
485
486 while ((end = strchr(start, ',')) && end == start)
487 start = end + 1;
488
489 if (!end)
490 return NULL;
491
492 *end = 0;
493 *cmds = end + 1;
494 return start;
495}
496
497static int ibm_acpi_driver_init(void)
498{
499 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
500 printk(IBM_INFO "%s\n", IBM_URL);
501
502 if (ibm_thinkpad_ec_found)
503 printk(IBM_INFO "ThinkPad EC firmware %s\n",
504 ibm_thinkpad_ec_found);
505
506 return 0;
507}
508
509static int driver_read(char *p)
510{
511 int len = 0;
512
513 len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC);
514 len += sprintf(p + len, "version:\t%s\n", IBM_VERSION);
515
516 return len;
517}
518
519static int hotkey_supported;
520static int hotkey_mask_supported;
521static int hotkey_orig_status;
522static int hotkey_orig_mask;
523
524static int hotkey_get(int *status, int *mask)
525{
526 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
527 return 0;
528
529 if (hotkey_mask_supported)
530 if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
531 return 0;
532
533 return 1;
534}
535
536static int hotkey_set(int status, int mask)
537{
538 int i;
539
540 if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
541 return 0;
542
543 if (hotkey_mask_supported)
544 for (i = 0; i < 32; i++) {
545 int bit = ((1 << i) & mask) != 0;
546 if (!acpi_evalf(hkey_handle,
547 NULL, "MHKM", "vdd", i + 1, bit))
548 return 0;
549 }
550
551 return 1;
552}
553
554static int hotkey_init(void)
555{
556 /* hotkey not supported on 570 */
557 hotkey_supported = hkey_handle != NULL;
558
559 if (hotkey_supported) {
560 /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
561 A30, R30, R31, T20-22, X20-21, X22-24 */
562 hotkey_mask_supported =
563 acpi_evalf(hkey_handle, NULL, "DHKN", "qv");
564
565 if (!hotkey_get(&hotkey_orig_status, &hotkey_orig_mask))
566 return -ENODEV;
567 }
568
569 return 0;
570}
571
572static int hotkey_read(char *p)
573{
574 int status, mask;
575 int len = 0;
576
577 if (!hotkey_supported) {
578 len += sprintf(p + len, "status:\t\tnot supported\n");
579 return len;
580 }
581
582 if (!hotkey_get(&status, &mask))
583 return -EIO;
584
585 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
586 if (hotkey_mask_supported) {
587 len += sprintf(p + len, "mask:\t\t0x%04x\n", mask);
588 len += sprintf(p + len,
589 "commands:\tenable, disable, reset, <mask>\n");
590 } else {
591 len += sprintf(p + len, "mask:\t\tnot supported\n");
592 len += sprintf(p + len, "commands:\tenable, disable, reset\n");
593 }
594
595 return len;
596}
597
598static int hotkey_write(char *buf)
599{
600 int status, mask;
601 char *cmd;
602 int do_cmd = 0;
603
604 if (!hotkey_supported)
605 return -ENODEV;
606
607 if (!hotkey_get(&status, &mask))
608 return -EIO;
609
610 while ((cmd = next_cmd(&buf))) {
611 if (strlencmp(cmd, "enable") == 0) {
612 status = 1;
613 } else if (strlencmp(cmd, "disable") == 0) {
614 status = 0;
615 } else if (strlencmp(cmd, "reset") == 0) {
616 status = hotkey_orig_status;
617 mask = hotkey_orig_mask;
618 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
619 /* mask set */
620 } else if (sscanf(cmd, "%x", &mask) == 1) {
621 /* mask set */
622 } else
623 return -EINVAL;
624 do_cmd = 1;
625 }
626
627 if (do_cmd && !hotkey_set(status, mask))
628 return -EIO;
629
630 return 0;
631}
632
633static void hotkey_exit(void)
634{
635 if (hotkey_supported)
636 hotkey_set(hotkey_orig_status, hotkey_orig_mask);
637}
638
639static void hotkey_notify(struct ibm_struct *ibm, u32 event)
640{
641 int hkey;
642
643 if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d"))
644 acpi_bus_generate_event(ibm->device, event, hkey);
645 else {
646 printk(IBM_ERR "unknown hotkey event %d\n", event);
647 acpi_bus_generate_event(ibm->device, event, 0);
648 }
649}
650
651static int bluetooth_supported;
652
653static int bluetooth_init(void)
654{
655 /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
656 G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
657 bluetooth_supported = hkey_handle &&
658 acpi_evalf(hkey_handle, NULL, "GBDC", "qv");
659
660 return 0;
661}
662
663static int bluetooth_status(void)
664{
665 int status;
666
667 if (!bluetooth_supported ||
668 !acpi_evalf(hkey_handle, &status, "GBDC", "d"))
669 status = 0;
670
671 return status;
672}
673
674static int bluetooth_read(char *p)
675{
676 int len = 0;
677 int status = bluetooth_status();
678
679 if (!bluetooth_supported)
680 len += sprintf(p + len, "status:\t\tnot supported\n");
681 else if (!(status & 1))
682 len += sprintf(p + len, "status:\t\tnot installed\n");
683 else {
684 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1));
685 len += sprintf(p + len, "commands:\tenable, disable\n");
686 }
687
688 return len;
689}
690
691static int bluetooth_write(char *buf)
692{
693 int status = bluetooth_status();
694 char *cmd;
695 int do_cmd = 0;
696
697 if (!bluetooth_supported)
698 return -ENODEV;
699
700 while ((cmd = next_cmd(&buf))) {
701 if (strlencmp(cmd, "enable") == 0) {
702 status |= 2;
703 } else if (strlencmp(cmd, "disable") == 0) {
704 status &= ~2;
705 } else
706 return -EINVAL;
707 do_cmd = 1;
708 }
709
710 if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
711 return -EIO;
712
713 return 0;
714}
715
716static int wan_supported;
717
718static int wan_init(void)
719{
720 wan_supported = hkey_handle &&
721 acpi_evalf(hkey_handle, NULL, "GWAN", "qv");
722
723 return 0;
724}
725
726static int wan_status(void)
727{
728 int status;
729
730 if (!wan_supported || !acpi_evalf(hkey_handle, &status, "GWAN", "d"))
731 status = 0;
732
733 return status;
734}
735
736static int wan_read(char *p)
737{
738 int len = 0;
739 int status = wan_status();
740
741 if (!wan_supported)
742 len += sprintf(p + len, "status:\t\tnot supported\n");
743 else if (!(status & 1))
744 len += sprintf(p + len, "status:\t\tnot installed\n");
745 else {
746 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1));
747 len += sprintf(p + len, "commands:\tenable, disable\n");
748 }
749
750 return len;
751}
752
753static int wan_write(char *buf)
754{
755 int status = wan_status();
756 char *cmd;
757 int do_cmd = 0;
758
759 if (!wan_supported)
760 return -ENODEV;
761
762 while ((cmd = next_cmd(&buf))) {
763 if (strlencmp(cmd, "enable") == 0) {
764 status |= 2;
765 } else if (strlencmp(cmd, "disable") == 0) {
766 status &= ~2;
767 } else
768 return -EINVAL;
769 do_cmd = 1;
770 }
771
772 if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
773 return -EIO;
774
775 return 0;
776}
777
778enum video_access_mode {
779 IBMACPI_VIDEO_NONE = 0,
780 IBMACPI_VIDEO_570, /* 570 */
781 IBMACPI_VIDEO_770, /* 600e/x, 770e, 770x */
782 IBMACPI_VIDEO_NEW, /* all others */
783};
784
785static enum video_access_mode video_supported;
786static int video_orig_autosw;
787
788static int video_init(void)
789{
790 int ivga;
791
792 if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
793 /* G41, assume IVGA doesn't change */
794 vid_handle = vid2_handle;
795
796 if (!vid_handle)
797 /* video switching not supported on R30, R31 */
798 video_supported = IBMACPI_VIDEO_NONE;
799 else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
800 /* 570 */
801 video_supported = IBMACPI_VIDEO_570;
802 else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
803 /* 600e/x, 770e, 770x */
804 video_supported = IBMACPI_VIDEO_770;
805 else
806 /* all others */
807 video_supported = IBMACPI_VIDEO_NEW;
808
809 return 0;
810}
811
812static int video_status(void)
813{
814 int status = 0;
815 int i;
816
817 if (video_supported == IBMACPI_VIDEO_570) {
818 if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87))
819 status = i & 3;
820 } else if (video_supported == IBMACPI_VIDEO_770) {
821 if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
822 status |= 0x01 * i;
823 if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
824 status |= 0x02 * i;
825 } else if (video_supported == IBMACPI_VIDEO_NEW) {
826 acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
827 if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
828 status |= 0x02 * i;
829
830 acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0);
831 if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
832 status |= 0x01 * i;
833 if (acpi_evalf(NULL, &i, "\\VCDD", "d"))
834 status |= 0x08 * i;
835 }
836
837 return status;
838}
839
840static int video_autosw(void)
841{
842 int autosw = 0;
843
844 if (video_supported == IBMACPI_VIDEO_570)
845 acpi_evalf(vid_handle, &autosw, "SWIT", "d");
846 else if (video_supported == IBMACPI_VIDEO_770 ||
847 video_supported == IBMACPI_VIDEO_NEW)
848 acpi_evalf(vid_handle, &autosw, "^VDEE", "d");
849
850 return autosw & 1;
851}
852
853static int video_read(char *p)
854{
855 int status = video_status();
856 int autosw = video_autosw();
857 int len = 0;
858
859 if (!video_supported) {
860 len += sprintf(p + len, "status:\t\tnot supported\n");
861 return len;
862 }
863
864 len += sprintf(p + len, "status:\t\tsupported\n");
865 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
866 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
867 if (video_supported == IBMACPI_VIDEO_NEW)
868 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
869 len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
870 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
871 len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
872 if (video_supported == IBMACPI_VIDEO_NEW)
873 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
874 len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
875 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
876
877 return len;
878}
879
880static int video_switch(void)
881{
882 int autosw = video_autosw();
883 int ret;
884
885 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
886 return -EIO;
887 ret = video_supported == IBMACPI_VIDEO_570 ?
888 acpi_evalf(ec_handle, NULL, "_Q16", "v") :
889 acpi_evalf(vid_handle, NULL, "VSWT", "v");
890 acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
891
892 return ret;
893}
894
895static int video_expand(void)
896{
897 if (video_supported == IBMACPI_VIDEO_570)
898 return acpi_evalf(ec_handle, NULL, "_Q17", "v");
899 else if (video_supported == IBMACPI_VIDEO_770)
900 return acpi_evalf(vid_handle, NULL, "VEXP", "v");
901 else
902 return acpi_evalf(NULL, NULL, "\\VEXP", "v");
903}
904
905static int video_switch2(int status)
906{
907 int ret;
908
909 if (video_supported == IBMACPI_VIDEO_570) {
910 ret = acpi_evalf(NULL, NULL,
911 "\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
912 } else if (video_supported == IBMACPI_VIDEO_770) {
913 int autosw = video_autosw();
914 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
915 return -EIO;
916
917 ret = acpi_evalf(vid_handle, NULL,
918 "ASWT", "vdd", status * 0x100, 0);
919
920 acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
921 } else {
922 ret = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
923 acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
924 }
925
926 return ret;
927}
928
929static int video_write(char *buf)
930{
931 char *cmd;
932 int enable, disable, status;
933
934 if (!video_supported)
935 return -ENODEV;
936
937 enable = disable = 0;
938
939 while ((cmd = next_cmd(&buf))) {
940 if (strlencmp(cmd, "lcd_enable") == 0) {
941 enable |= 0x01;
942 } else if (strlencmp(cmd, "lcd_disable") == 0) {
943 disable |= 0x01;
944 } else if (strlencmp(cmd, "crt_enable") == 0) {
945 enable |= 0x02;
946 } else if (strlencmp(cmd, "crt_disable") == 0) {
947 disable |= 0x02;
948 } else if (video_supported == IBMACPI_VIDEO_NEW &&
949 strlencmp(cmd, "dvi_enable") == 0) {
950 enable |= 0x08;
951 } else if (video_supported == IBMACPI_VIDEO_NEW &&
952 strlencmp(cmd, "dvi_disable") == 0) {
953 disable |= 0x08;
954 } else if (strlencmp(cmd, "auto_enable") == 0) {
955 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
956 return -EIO;
957 } else if (strlencmp(cmd, "auto_disable") == 0) {
958 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 0))
959 return -EIO;
960 } else if (strlencmp(cmd, "video_switch") == 0) {
961 if (!video_switch())
962 return -EIO;
963 } else if (strlencmp(cmd, "expand_toggle") == 0) {
964 if (!video_expand())
965 return -EIO;
966 } else
967 return -EINVAL;
968 }
969
970 if (enable || disable) {
971 status = (video_status() & 0x0f & ~disable) | enable;
972 if (!video_switch2(status))
973 return -EIO;
974 }
975
976 return 0;
977}
978
979static void video_exit(void)
980{
981 acpi_evalf(vid_handle, NULL, "_DOS", "vd", video_orig_autosw);
982}
983
984static int light_supported;
985static int light_status_supported;
986
987static int light_init(void)
988{
989 /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
990 light_supported = (cmos_handle || lght_handle) && !ledb_handle;
991
992 if (light_supported)
993 /* light status not supported on
994 570, 600e/x, 770e, 770x, G4x, R30, R31, R32, X20 */
995 light_status_supported = acpi_evalf(ec_handle, NULL,
996 "KBLT", "qv");
997
998 return 0;
999}
1000
1001static int light_read(char *p)
1002{
1003 int len = 0;
1004 int status = 0;
1005
1006 if (!light_supported) {
1007 len += sprintf(p + len, "status:\t\tnot supported\n");
1008 } else if (!light_status_supported) {
1009 len += sprintf(p + len, "status:\t\tunknown\n");
1010 len += sprintf(p + len, "commands:\ton, off\n");
1011 } else {
1012 if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
1013 return -EIO;
1014 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
1015 len += sprintf(p + len, "commands:\ton, off\n");
1016 }
1017
1018 return len;
1019}
1020
1021static int light_write(char *buf)
1022{
1023 int cmos_cmd, lght_cmd;
1024 char *cmd;
1025 int success;
1026
1027 if (!light_supported)
1028 return -ENODEV;
1029
1030 while ((cmd = next_cmd(&buf))) {
1031 if (strlencmp(cmd, "on") == 0) {
1032 cmos_cmd = 0x0c;
1033 lght_cmd = 1;
1034 } else if (strlencmp(cmd, "off") == 0) {
1035 cmos_cmd = 0x0d;
1036 lght_cmd = 0;
1037 } else
1038 return -EINVAL;
1039
1040 success = cmos_handle ?
1041 acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
1042 acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
1043 if (!success)
1044 return -EIO;
1045 }
1046
1047 return 0;
1048}
1049
1050#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY)
1051static int _sta(acpi_handle handle)
1052{
1053 int status;
1054
1055 if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
1056 status = 0;
1057
1058 return status;
1059}
1060#endif
1061
1062#ifdef CONFIG_ACPI_IBM_DOCK
1063#define dock_docked() (_sta(dock_handle) & 1)
1064
1065static int dock_read(char *p)
1066{
1067 int len = 0;
1068 int docked = dock_docked();
1069
1070 if (!dock_handle)
1071 len += sprintf(p + len, "status:\t\tnot supported\n");
1072 else if (!docked)
1073 len += sprintf(p + len, "status:\t\tundocked\n");
1074 else {
1075 len += sprintf(p + len, "status:\t\tdocked\n");
1076 len += sprintf(p + len, "commands:\tdock, undock\n");
1077 }
1078
1079 return len;
1080}
1081
1082static int dock_write(char *buf)
1083{
1084 char *cmd;
1085
1086 if (!dock_docked())
1087 return -ENODEV;
1088
1089 while ((cmd = next_cmd(&buf))) {
1090 if (strlencmp(cmd, "undock") == 0) {
1091 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
1092 !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
1093 return -EIO;
1094 } else if (strlencmp(cmd, "dock") == 0) {
1095 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
1096 return -EIO;
1097 } else
1098 return -EINVAL;
1099 }
1100
1101 return 0;
1102}
1103
1104static void dock_notify(struct ibm_struct *ibm, u32 event)
1105{
1106 int docked = dock_docked();
1107 int pci = ibm->hid && strstr(ibm->hid, IBM_PCI_HID);
1108
1109 if (event == 1 && !pci) /* 570 */
1110 acpi_bus_generate_event(ibm->device, event, 1); /* button */
1111 else if (event == 1 && pci) /* 570 */
1112 acpi_bus_generate_event(ibm->device, event, 3); /* dock */
1113 else if (event == 3 && docked)
1114 acpi_bus_generate_event(ibm->device, event, 1); /* button */
1115 else if (event == 3 && !docked)
1116 acpi_bus_generate_event(ibm->device, event, 2); /* undock */
1117 else if (event == 0 && docked)
1118 acpi_bus_generate_event(ibm->device, event, 3); /* dock */
1119 else {
1120 printk(IBM_ERR "unknown dock event %d, status %d\n",
1121 event, _sta(dock_handle));
1122 acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
1123 }
1124}
1125#endif
1126
1127#ifdef CONFIG_ACPI_IBM_BAY
1128static int bay_status_supported;
1129static int bay_status2_supported;
1130static int bay_eject_supported;
1131static int bay_eject2_supported;
1132
1133static int bay_init(void)
1134{
1135 bay_status_supported = bay_handle &&
1136 acpi_evalf(bay_handle, NULL, "_STA", "qv");
1137 bay_status2_supported = bay2_handle &&
1138 acpi_evalf(bay2_handle, NULL, "_STA", "qv");
1139
1140 bay_eject_supported = bay_handle && bay_ej_handle &&
1141 (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
1142 bay_eject2_supported = bay2_handle && bay2_ej_handle &&
1143 (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
1144
1145 return 0;
1146}
1147
1148#define bay_occupied(b) (_sta(b##_handle) & 1)
1149
1150static int bay_read(char *p)
1151{
1152 int len = 0;
1153 int occupied = bay_occupied(bay);
1154 int occupied2 = bay_occupied(bay2);
1155 int eject, eject2;
1156
1157 len += sprintf(p + len, "status:\t\t%s\n", bay_status_supported ?
1158 (occupied ? "occupied" : "unoccupied") :
1159 "not supported");
1160 if (bay_status2_supported)
1161 len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
1162 "occupied" : "unoccupied");
1163
1164 eject = bay_eject_supported && occupied;
1165 eject2 = bay_eject2_supported && occupied2;
1166
1167 if (eject && eject2)
1168 len += sprintf(p + len, "commands:\teject, eject2\n");
1169 else if (eject)
1170 len += sprintf(p + len, "commands:\teject\n");
1171 else if (eject2)
1172 len += sprintf(p + len, "commands:\teject2\n");
1173
1174 return len;
1175}
1176
1177static int bay_write(char *buf)
1178{
1179 char *cmd;
1180
1181 if (!bay_eject_supported && !bay_eject2_supported)
1182 return -ENODEV;
1183
1184 while ((cmd = next_cmd(&buf))) {
1185 if (bay_eject_supported && strlencmp(cmd, "eject") == 0) {
1186 if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
1187 return -EIO;
1188 } else if (bay_eject2_supported &&
1189 strlencmp(cmd, "eject2") == 0) {
1190 if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
1191 return -EIO;
1192 } else
1193 return -EINVAL;
1194 }
1195
1196 return 0;
1197}
1198
1199static void bay_notify(struct ibm_struct *ibm, u32 event)
1200{
1201 acpi_bus_generate_event(ibm->device, event, 0);
1202}
1203#endif /* CONFIG_ACPI_IBM_BAY */
1204
1205static int cmos_read(char *p)
1206{
1207 int len = 0;
1208
1209 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
1210 R30, R31, T20-22, X20-21 */
1211 if (!cmos_handle)
1212 len += sprintf(p + len, "status:\t\tnot supported\n");
1213 else {
1214 len += sprintf(p + len, "status:\t\tsupported\n");
1215 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
1216 }
1217
1218 return len;
1219}
1220
1221static int cmos_eval(int cmos_cmd)
1222{
1223 if (cmos_handle)
1224 return acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd);
1225 else
1226 return 1;
1227}
1228
1229static int cmos_write(char *buf)
1230{
1231 char *cmd;
1232 int cmos_cmd;
1233
1234 if (!cmos_handle)
1235 return -EINVAL;
1236
1237 while ((cmd = next_cmd(&buf))) {
1238 if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
1239 cmos_cmd >= 0 && cmos_cmd <= 21) {
1240 /* cmos_cmd set */
1241 } else
1242 return -EINVAL;
1243
1244 if (!cmos_eval(cmos_cmd))
1245 return -EIO;
1246 }
1247
1248 return 0;
1249}
1250
1251enum led_access_mode {
1252 IBMACPI_LED_NONE = 0,
1253 IBMACPI_LED_570, /* 570 */
1254 IBMACPI_LED_OLD, /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
1255 IBMACPI_LED_NEW, /* all others */
1256};
1257static enum led_access_mode led_supported;
1258
1259static int led_init(void)
1260{
1261 if (!led_handle)
1262 /* led not supported on R30, R31 */
1263 led_supported = IBMACPI_LED_NONE;
1264 else if (strlencmp(led_path, "SLED") == 0)
1265 /* 570 */
1266 led_supported = IBMACPI_LED_570;
1267 else if (strlencmp(led_path, "SYSL") == 0)
1268 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
1269 led_supported = IBMACPI_LED_OLD;
1270 else
1271 /* all others */
1272 led_supported = IBMACPI_LED_NEW;
1273
1274 return 0;
1275}
1276
1277#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
1278
1279static int led_read(char *p)
1280{
1281 int len = 0;
1282
1283 if (!led_supported) {
1284 len += sprintf(p + len, "status:\t\tnot supported\n");
1285 return len;
1286 }
1287 len += sprintf(p + len, "status:\t\tsupported\n");
1288
1289 if (led_supported == IBMACPI_LED_570) {
1290 /* 570 */
1291 int i, status;
1292 for (i = 0; i < 8; i++) {
1293 if (!acpi_evalf(ec_handle,
1294 &status, "GLED", "dd", 1 << i))
1295 return -EIO;
1296 len += sprintf(p + len, "%d:\t\t%s\n",
1297 i, led_status(status));
1298 }
1299 }
1300
1301 len += sprintf(p + len, "commands:\t"
1302 "<led> on, <led> off, <led> blink (<led> is 0-7)\n");
1303
1304 return len;
1305}
1306
1307/* off, on, blink */
1308static const int led_sled_arg1[] = { 0, 1, 3 };
1309static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
1310static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
1311static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
1312
1313#define EC_HLCL 0x0c
1314#define EC_HLBL 0x0d
1315#define EC_HLMS 0x0e
1316
1317static int led_write(char *buf)
1318{
1319 char *cmd;
1320 int led, ind, ret;
1321
1322 if (!led_supported)
1323 return -ENODEV;
1324
1325 while ((cmd = next_cmd(&buf))) {
1326 if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7)
1327 return -EINVAL;
1328
1329 if (strstr(cmd, "off")) {
1330 ind = 0;
1331 } else if (strstr(cmd, "on")) {
1332 ind = 1;
1333 } else if (strstr(cmd, "blink")) {
1334 ind = 2;
1335 } else
1336 return -EINVAL;
1337
1338 if (led_supported == IBMACPI_LED_570) {
1339 /* 570 */
1340 led = 1 << led;
1341 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
1342 led, led_sled_arg1[ind]))
1343 return -EIO;
1344 } else if (led_supported == IBMACPI_LED_OLD) {
1345 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
1346 led = 1 << led;
1347 ret = ec_write(EC_HLMS, led);
1348 if (ret >= 0)
1349 ret =
1350 ec_write(EC_HLBL, led * led_exp_hlbl[ind]);
1351 if (ret >= 0)
1352 ret =
1353 ec_write(EC_HLCL, led * led_exp_hlcl[ind]);
1354 if (ret < 0)
1355 return ret;
1356 } else {
1357 /* all others */
1358 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
1359 led, led_led_arg1[ind]))
1360 return -EIO;
1361 }
1362 }
1363
1364 return 0;
1365}
1366
1367static int beep_read(char *p)
1368{
1369 int len = 0;
1370
1371 if (!beep_handle)
1372 len += sprintf(p + len, "status:\t\tnot supported\n");
1373 else {
1374 len += sprintf(p + len, "status:\t\tsupported\n");
1375 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
1376 }
1377
1378 return len;
1379}
1380
1381static int beep_write(char *buf)
1382{
1383 char *cmd;
1384 int beep_cmd;
1385
1386 if (!beep_handle)
1387 return -ENODEV;
1388
1389 while ((cmd = next_cmd(&buf))) {
1390 if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
1391 beep_cmd >= 0 && beep_cmd <= 17) {
1392 /* beep_cmd set */
1393 } else
1394 return -EINVAL;
1395 if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0))
1396 return -EIO;
1397 }
1398
1399 return 0;
1400}
1401
1402static int acpi_ec_read(int i, u8 * p)
1403{
1404 int v;
1405
1406 if (ecrd_handle) {
1407 if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
1408 return 0;
1409 *p = v;
1410 } else {
1411 if (ec_read(i, p) < 0)
1412 return 0;
1413 }
1414
1415 return 1;
1416}
1417
1418static int acpi_ec_write(int i, u8 v)
1419{
1420 if (ecwr_handle) {
1421 if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
1422 return 0;
1423 } else {
1424 if (ec_write(i, v) < 0)
1425 return 0;
1426 }
1427
1428 return 1;
1429}
1430
1431static enum thermal_access_mode thermal_read_mode;
1432
1433static int thermal_init(void)
1434{
1435 u8 t, ta1, ta2;
1436 int i;
1437 int acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
1438
1439 if (ibm_thinkpad_ec_found && experimental) {
1440 /*
1441 * Direct EC access mode: sensors at registers
1442 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for
1443 * non-implemented, thermal sensors return 0x80 when
1444 * not available
1445 */
1446
1447 ta1 = ta2 = 0;
1448 for (i = 0; i < 8; i++) {
1449 if (likely(acpi_ec_read(0x78 + i, &t))) {
1450 ta1 |= t;
1451 } else {
1452 ta1 = 0;
1453 break;
1454 }
1455 if (likely(acpi_ec_read(0xC0 + i, &t))) {
1456 ta2 |= t;
1457 } else {
1458 ta1 = 0;
1459 break;
1460 }
1461 }
1462 if (ta1 == 0) {
1463 /* This is sheer paranoia, but we handle it anyway */
1464 if (acpi_tmp7) {
1465 printk(IBM_ERR
1466 "ThinkPad ACPI EC access misbehaving, "
1467 "falling back to ACPI TMPx access mode\n");
1468 thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
1469 } else {
1470 printk(IBM_ERR
1471 "ThinkPad ACPI EC access misbehaving, "
1472 "disabling thermal sensors access\n");
1473 thermal_read_mode = IBMACPI_THERMAL_NONE;
1474 }
1475 } else {
1476 thermal_read_mode =
1477 (ta2 != 0) ?
1478 IBMACPI_THERMAL_TPEC_16 : IBMACPI_THERMAL_TPEC_8;
1479 }
1480 } else if (acpi_tmp7) {
1481 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
1482 /* 600e/x, 770e, 770x */
1483 thermal_read_mode = IBMACPI_THERMAL_ACPI_UPDT;
1484 } else {
1485 /* Standard ACPI TMPx access, max 8 sensors */
1486 thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
1487 }
1488 } else {
1489 /* temperatures not supported on 570, G4x, R30, R31, R32 */
1490 thermal_read_mode = IBMACPI_THERMAL_NONE;
1491 }
1492
1493 return 0;
1494}
1495
1496static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
1497{
1498 int i, t;
1499 s8 tmp;
1500 char tmpi[] = "TMPi";
1501
1502 if (!s)
1503 return -EINVAL;
1504
1505 switch (thermal_read_mode) {
1506#if IBMACPI_MAX_THERMAL_SENSORS >= 16
1507 case IBMACPI_THERMAL_TPEC_16:
1508 for (i = 0; i < 8; i++) {
1509 if (!acpi_ec_read(0xC0 + i, &tmp))
1510 return -EIO;
1511 s->temp[i + 8] = tmp * 1000;
1512 }
1513 /* fallthrough */
1514#endif
1515 case IBMACPI_THERMAL_TPEC_8:
1516 for (i = 0; i < 8; i++) {
1517 if (!acpi_ec_read(0x78 + i, &tmp))
1518 return -EIO;
1519 s->temp[i] = tmp * 1000;
1520 }
1521 return (thermal_read_mode == IBMACPI_THERMAL_TPEC_16) ? 16 : 8;
1522
1523 case IBMACPI_THERMAL_ACPI_UPDT:
1524 if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
1525 return -EIO;
1526 for (i = 0; i < 8; i++) {
1527 tmpi[3] = '0' + i;
1528 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
1529 return -EIO;
1530 s->temp[i] = (t - 2732) * 100;
1531 }
1532 return 8;
1533
1534 case IBMACPI_THERMAL_ACPI_TMP07:
1535 for (i = 0; i < 8; i++) {
1536 tmpi[3] = '0' + i;
1537 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
1538 return -EIO;
1539 s->temp[i] = t * 1000;
1540 }
1541 return 8;
1542
1543 case IBMACPI_THERMAL_NONE:
1544 default:
1545 return 0;
1546 }
1547}
1548
1549static int thermal_read(char *p)
1550{
1551 int len = 0;
1552 int n, i;
1553 struct ibm_thermal_sensors_struct t;
1554
1555 n = thermal_get_sensors(&t);
1556 if (unlikely(n < 0))
1557 return n;
1558
1559 len += sprintf(p + len, "temperatures:\t");
1560
1561 if (n > 0) {
1562 for (i = 0; i < (n - 1); i++)
1563 len += sprintf(p + len, "%d ", t.temp[i] / 1000);
1564 len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
1565 } else
1566 len += sprintf(p + len, "not supported\n");
1567
1568 return len;
1569}
1570
1571static u8 ecdump_regs[256];
1572
1573static int ecdump_read(char *p)
1574{
1575 int len = 0;
1576 int i, j;
1577 u8 v;
1578
1579 len += sprintf(p + len, "EC "
1580 " +00 +01 +02 +03 +04 +05 +06 +07"
1581 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
1582 for (i = 0; i < 256; i += 16) {
1583 len += sprintf(p + len, "EC 0x%02x:", i);
1584 for (j = 0; j < 16; j++) {
1585 if (!acpi_ec_read(i + j, &v))
1586 break;
1587 if (v != ecdump_regs[i + j])
1588 len += sprintf(p + len, " *%02x", v);
1589 else
1590 len += sprintf(p + len, " %02x", v);
1591 ecdump_regs[i + j] = v;
1592 }
1593 len += sprintf(p + len, "\n");
1594 if (j != 16)
1595 break;
1596 }
1597
1598 /* These are way too dangerous to advertise openly... */
1599#if 0
1600 len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
1601 " (<offset> is 00-ff, <value> is 00-ff)\n");
1602 len += sprintf(p + len, "commands:\t0x<offset> <value> "
1603 " (<offset> is 00-ff, <value> is 0-255)\n");
1604#endif
1605 return len;
1606}
1607
1608static int ecdump_write(char *buf)
1609{
1610 char *cmd;
1611 int i, v;
1612
1613 while ((cmd = next_cmd(&buf))) {
1614 if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
1615 /* i and v set */
1616 } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
1617 /* i and v set */
1618 } else
1619 return -EINVAL;
1620 if (i >= 0 && i < 256 && v >= 0 && v < 256) {
1621 if (!acpi_ec_write(i, v))
1622 return -EIO;
1623 } else
1624 return -EINVAL;
1625 }
1626
1627 return 0;
1628}
1629
1630static int brightness_offset = 0x31;
1631
1632static int brightness_get(struct backlight_device *bd)
1633{
1634 u8 level;
1635 if (!acpi_ec_read(brightness_offset, &level))
1636 return -EIO;
1637
1638 level &= 0x7;
1639
1640 return level;
1641}
1642
1643static int brightness_read(char *p)
1644{
1645 int len = 0;
1646 int level;
1647
1648 if ((level = brightness_get(NULL)) < 0) {
1649 len += sprintf(p + len, "level:\t\tunreadable\n");
1650 } else {
1651 len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
1652 len += sprintf(p + len, "commands:\tup, down\n");
1653 len += sprintf(p + len, "commands:\tlevel <level>"
1654 " (<level> is 0-7)\n");
1655 }
1656
1657 return len;
1658}
1659
1660#define BRIGHTNESS_UP 4
1661#define BRIGHTNESS_DOWN 5
1662
1663static int brightness_set(int value)
1664{
1665 int cmos_cmd, inc, i;
1666 int current_value = brightness_get(NULL);
1667
1668 value &= 7;
1669
1670 cmos_cmd = value > current_value ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
1671 inc = value > current_value ? 1 : -1;
1672 for (i = current_value; i != value; i += inc) {
1673 if (!cmos_eval(cmos_cmd))
1674 return -EIO;
1675 if (!acpi_ec_write(brightness_offset, i + inc))
1676 return -EIO;
1677 }
1678
1679 return 0;
1680}
1681
1682static int brightness_write(char *buf)
1683{
1684 int level;
1685 int new_level;
1686 char *cmd;
1687
1688 while ((cmd = next_cmd(&buf))) {
1689 if ((level = brightness_get(NULL)) < 0)
1690 return level;
1691 level &= 7;
1692
1693 if (strlencmp(cmd, "up") == 0) {
1694 new_level = level == 7 ? 7 : level + 1;
1695 } else if (strlencmp(cmd, "down") == 0) {
1696 new_level = level == 0 ? 0 : level - 1;
1697 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
1698 new_level >= 0 && new_level <= 7) {
1699 /* new_level set */
1700 } else
1701 return -EINVAL;
1702
1703 brightness_set(new_level);
1704 }
1705
1706 return 0;
1707}
1708
1709static int brightness_update_status(struct backlight_device *bd)
1710{
1711 return brightness_set(
1712 (bd->props.fb_blank == FB_BLANK_UNBLANK &&
1713 bd->props.power == FB_BLANK_UNBLANK) ?
1714 bd->props.brightness : 0);
1715}
1716
1717static struct backlight_ops ibm_backlight_data = {
1718 .get_brightness = brightness_get,
1719 .update_status = brightness_update_status,
1720};
1721
1722static int brightness_init(void)
1723{
1724 int b;
1725
1726 b = brightness_get(NULL);
1727 if (b < 0)
1728 return b;
1729
1730 ibm_backlight_device = backlight_device_register("ibm", NULL, NULL,
1731 &ibm_backlight_data);
1732 if (IS_ERR(ibm_backlight_device)) {
1733 printk(IBM_ERR "Could not register backlight device\n");
1734 return PTR_ERR(ibm_backlight_device);
1735 }
1736
1737 ibm_backlight_device->props.max_brightness = 7;
1738 ibm_backlight_device->props.brightness = b;
1739 backlight_update_status(ibm_backlight_device);
1740
1741 return 0;
1742}
1743
1744static void brightness_exit(void)
1745{
1746 if (ibm_backlight_device) {
1747 backlight_device_unregister(ibm_backlight_device);
1748 ibm_backlight_device = NULL;
1749 }
1750}
1751
1752static int volume_offset = 0x30;
1753
1754static int volume_read(char *p)
1755{
1756 int len = 0;
1757 u8 level;
1758
1759 if (!acpi_ec_read(volume_offset, &level)) {
1760 len += sprintf(p + len, "level:\t\tunreadable\n");
1761 } else {
1762 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
1763 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
1764 len += sprintf(p + len, "commands:\tup, down, mute\n");
1765 len += sprintf(p + len, "commands:\tlevel <level>"
1766 " (<level> is 0-15)\n");
1767 }
1768
1769 return len;
1770}
1771
1772#define VOLUME_DOWN 0
1773#define VOLUME_UP 1
1774#define VOLUME_MUTE 2
1775
1776static int volume_write(char *buf)
1777{
1778 int cmos_cmd, inc, i;
1779 u8 level, mute;
1780 int new_level, new_mute;
1781 char *cmd;
1782
1783 while ((cmd = next_cmd(&buf))) {
1784 if (!acpi_ec_read(volume_offset, &level))
1785 return -EIO;
1786 new_mute = mute = level & 0x40;
1787 new_level = level = level & 0xf;
1788
1789 if (strlencmp(cmd, "up") == 0) {
1790 if (mute)
1791 new_mute = 0;
1792 else
1793 new_level = level == 15 ? 15 : level + 1;
1794 } else if (strlencmp(cmd, "down") == 0) {
1795 if (mute)
1796 new_mute = 0;
1797 else
1798 new_level = level == 0 ? 0 : level - 1;
1799 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
1800 new_level >= 0 && new_level <= 15) {
1801 /* new_level set */
1802 } else if (strlencmp(cmd, "mute") == 0) {
1803 new_mute = 0x40;
1804 } else
1805 return -EINVAL;
1806
1807 if (new_level != level) { /* mute doesn't change */
1808 cmos_cmd = new_level > level ? VOLUME_UP : VOLUME_DOWN;
1809 inc = new_level > level ? 1 : -1;
1810
1811 if (mute && (!cmos_eval(cmos_cmd) ||
1812 !acpi_ec_write(volume_offset, level)))
1813 return -EIO;
1814
1815 for (i = level; i != new_level; i += inc)
1816 if (!cmos_eval(cmos_cmd) ||
1817 !acpi_ec_write(volume_offset, i + inc))
1818 return -EIO;
1819
1820 if (mute && (!cmos_eval(VOLUME_MUTE) ||
1821 !acpi_ec_write(volume_offset,
1822 new_level + mute)))
1823 return -EIO;
1824 }
1825
1826 if (new_mute != mute) { /* level doesn't change */
1827 cmos_cmd = new_mute ? VOLUME_MUTE : VOLUME_UP;
1828
1829 if (!cmos_eval(cmos_cmd) ||
1830 !acpi_ec_write(volume_offset, level + new_mute))
1831 return -EIO;
1832 }
1833 }
1834
1835 return 0;
1836}
1837
1838static enum fan_status_access_mode fan_status_access_mode;
1839static enum fan_control_access_mode fan_control_access_mode;
1840static enum fan_control_commands fan_control_commands;
1841
1842static int fan_control_status_known;
1843static u8 fan_control_initial_status;
1844
1845static void fan_watchdog_fire(struct work_struct *ignored);
1846static int fan_watchdog_maxinterval;
1847static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
1848
1849static int fan_init(void)
1850{
1851 fan_status_access_mode = IBMACPI_FAN_NONE;
1852 fan_control_access_mode = IBMACPI_FAN_WR_NONE;
1853 fan_control_commands = 0;
1854 fan_control_status_known = 1;
1855 fan_watchdog_maxinterval = 0;
1856
1857 if (gfan_handle) {
1858 /* 570, 600e/x, 770e, 770x */
1859 fan_status_access_mode = IBMACPI_FAN_RD_ACPI_GFAN;
1860 } else {
1861 /* all other ThinkPads: note that even old-style
1862 * ThinkPad ECs supports the fan control register */
1863 if (likely(acpi_ec_read(fan_status_offset,
1864 &fan_control_initial_status))) {
1865 fan_status_access_mode = IBMACPI_FAN_RD_TPEC;
1866
1867 /* In some ThinkPads, neither the EC nor the ACPI
1868 * DSDT initialize the fan status, and it ends up
1869 * being set to 0x07 when it *could* be either
1870 * 0x07 or 0x80.
1871 *
1872 * Enable for TP-1Y (T43), TP-78 (R51e),
1873 * TP-76 (R52), TP-70 (T43, R52), which are known
1874 * to be buggy. */
1875 if (fan_control_initial_status == 0x07 &&
1876 ibm_thinkpad_ec_found &&
1877 ((ibm_thinkpad_ec_found[0] == '1' &&
1878 ibm_thinkpad_ec_found[1] == 'Y') ||
1879 (ibm_thinkpad_ec_found[0] == '7' &&
1880 (ibm_thinkpad_ec_found[1] == '6' ||
1881 ibm_thinkpad_ec_found[1] == '8' ||
1882 ibm_thinkpad_ec_found[1] == '0'))
1883 )) {
1884 printk(IBM_NOTICE
1885 "fan_init: initial fan status is "
1886 "unknown, assuming it is in auto "
1887 "mode\n");
1888 fan_control_status_known = 0;
1889 }
1890 } else {
1891 printk(IBM_ERR
1892 "ThinkPad ACPI EC access misbehaving, "
1893 "fan status and control unavailable\n");
1894 return 0;
1895 }
1896 }
1897
1898 if (sfan_handle) {
1899 /* 570, 770x-JL */
1900 fan_control_access_mode = IBMACPI_FAN_WR_ACPI_SFAN;
1901 fan_control_commands |=
1902 IBMACPI_FAN_CMD_LEVEL | IBMACPI_FAN_CMD_ENABLE;
1903 } else {
1904 if (!gfan_handle) {
1905 /* gfan without sfan means no fan control */
1906 /* all other models implement TP EC 0x2f control */
1907
1908 if (fans_handle) {
1909 /* X31, X40, X41 */
1910 fan_control_access_mode =
1911 IBMACPI_FAN_WR_ACPI_FANS;
1912 fan_control_commands |=
1913 IBMACPI_FAN_CMD_SPEED |
1914 IBMACPI_FAN_CMD_LEVEL |
1915 IBMACPI_FAN_CMD_ENABLE;
1916 } else {
1917 fan_control_access_mode = IBMACPI_FAN_WR_TPEC;
1918 fan_control_commands |=
1919 IBMACPI_FAN_CMD_LEVEL |
1920 IBMACPI_FAN_CMD_ENABLE;
1921 }
1922 }
1923 }
1924
1925 return 0;
1926}
1927
1928static int fan_get_status(u8 *status)
1929{
1930 u8 s;
1931
1932 /* TODO:
1933 * Add IBMACPI_FAN_RD_ACPI_FANS ? */
1934
1935 switch (fan_status_access_mode) {
1936 case IBMACPI_FAN_RD_ACPI_GFAN:
1937 /* 570, 600e/x, 770e, 770x */
1938
1939 if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
1940 return -EIO;
1941
1942 if (likely(status))
1943 *status = s & 0x07;
1944
1945 break;
1946
1947 case IBMACPI_FAN_RD_TPEC:
1948 /* all except 570, 600e/x, 770e, 770x */
1949 if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
1950 return -EIO;
1951
1952 if (likely(status))
1953 *status = s;
1954
1955 break;
1956
1957 default:
1958 return -ENXIO;
1959 }
1960
1961 return 0;
1962}
1963
1964static int fan_get_speed(unsigned int *speed)
1965{
1966 u8 hi, lo;
1967
1968 switch (fan_status_access_mode) {
1969 case IBMACPI_FAN_RD_TPEC:
1970 /* all except 570, 600e/x, 770e, 770x */
1971 if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
1972 !acpi_ec_read(fan_rpm_offset + 1, &hi)))
1973 return -EIO;
1974
1975 if (likely(speed))
1976 *speed = (hi << 8) | lo;
1977
1978 break;
1979
1980 default:
1981 return -ENXIO;
1982 }
1983
1984 return 0;
1985}
1986
1987static void fan_exit(void)
1988{
1989 cancel_delayed_work(&fan_watchdog_task);
1990 flush_scheduled_work();
1991}
1992
1993static void fan_watchdog_reset(void)
1994{
1995 static int fan_watchdog_active = 0;
1996
1997 if (fan_watchdog_active)
1998 cancel_delayed_work(&fan_watchdog_task);
1999
2000 if (fan_watchdog_maxinterval > 0) {
2001 fan_watchdog_active = 1;
2002 if (!schedule_delayed_work(&fan_watchdog_task,
2003 msecs_to_jiffies(fan_watchdog_maxinterval
2004 * 1000))) {
2005 printk(IBM_ERR "failed to schedule the fan watchdog, "
2006 "watchdog will not trigger\n");
2007 }
2008 } else
2009 fan_watchdog_active = 0;
2010}
2011
2012static int fan_read(char *p)
2013{
2014 int len = 0;
2015 int rc;
2016 u8 status;
2017 unsigned int speed = 0;
2018
2019 switch (fan_status_access_mode) {
2020 case IBMACPI_FAN_RD_ACPI_GFAN:
2021 /* 570, 600e/x, 770e, 770x */
2022 if ((rc = fan_get_status(&status)) < 0)
2023 return rc;
2024
2025 len += sprintf(p + len, "status:\t\t%s\n"
2026 "level:\t\t%d\n",
2027 (status != 0) ? "enabled" : "disabled", status);
2028 break;
2029
2030 case IBMACPI_FAN_RD_TPEC:
2031 /* all except 570, 600e/x, 770e, 770x */
2032 if ((rc = fan_get_status(&status)) < 0)
2033 return rc;
2034
2035 if (unlikely(!fan_control_status_known)) {
2036 if (status != fan_control_initial_status)
2037 fan_control_status_known = 1;
2038 else
2039 /* Return most likely status. In fact, it
2040 * might be the only possible status */
2041 status = IBMACPI_FAN_EC_AUTO;
2042 }
2043
2044 len += sprintf(p + len, "status:\t\t%s\n",
2045 (status != 0) ? "enabled" : "disabled");
2046
2047 /* No ThinkPad boots on disengaged mode, we can safely
2048 * assume the tachometer is online if fan control status
2049 * was unknown */
2050 if ((rc = fan_get_speed(&speed)) < 0)
2051 return rc;
2052
2053 len += sprintf(p + len, "speed:\t\t%d\n", speed);
2054
2055 if (status & IBMACPI_FAN_EC_DISENGAGED)
2056 /* Disengaged mode takes precedence */
2057 len += sprintf(p + len, "level:\t\tdisengaged\n");
2058 else if (status & IBMACPI_FAN_EC_AUTO)
2059 len += sprintf(p + len, "level:\t\tauto\n");
2060 else
2061 len += sprintf(p + len, "level:\t\t%d\n", status);
2062 break;
2063
2064 case IBMACPI_FAN_NONE:
2065 default:
2066 len += sprintf(p + len, "status:\t\tnot supported\n");
2067 }
2068
2069 if (fan_control_commands & IBMACPI_FAN_CMD_LEVEL) {
2070 len += sprintf(p + len, "commands:\tlevel <level>");
2071
2072 switch (fan_control_access_mode) {
2073 case IBMACPI_FAN_WR_ACPI_SFAN:
2074 len += sprintf(p + len, " (<level> is 0-7)\n");
2075 break;
2076
2077 default:
2078 len += sprintf(p + len, " (<level> is 0-7, "
2079 "auto, disengaged)\n");
2080 break;
2081 }
2082 }
2083
2084 if (fan_control_commands & IBMACPI_FAN_CMD_ENABLE)
2085 len += sprintf(p + len, "commands:\tenable, disable\n"
2086 "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
2087 "1-120 (seconds))\n");
2088
2089 if (fan_control_commands & IBMACPI_FAN_CMD_SPEED)
2090 len += sprintf(p + len, "commands:\tspeed <speed>"
2091 " (<speed> is 0-65535)\n");
2092
2093 return len;
2094}
2095
2096static int fan_set_level(int level)
2097{
2098 switch (fan_control_access_mode) {
2099 case IBMACPI_FAN_WR_ACPI_SFAN:
2100 if (level >= 0 && level <= 7) {
2101 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
2102 return -EIO;
2103 } else
2104 return -EINVAL;
2105 break;
2106
2107 case IBMACPI_FAN_WR_ACPI_FANS:
2108 case IBMACPI_FAN_WR_TPEC:
2109 if ((level != IBMACPI_FAN_EC_AUTO) &&
2110 (level != IBMACPI_FAN_EC_DISENGAGED) &&
2111 ((level < 0) || (level > 7)))
2112 return -EINVAL;
2113
2114 if (!acpi_ec_write(fan_status_offset, level))
2115 return -EIO;
2116 else
2117 fan_control_status_known = 1;
2118 break;
2119
2120 default:
2121 return -ENXIO;
2122 }
2123 return 0;
2124}
2125
2126static int fan_set_enable(void)
2127{
2128 u8 s;
2129 int rc;
2130
2131 switch (fan_control_access_mode) {
2132 case IBMACPI_FAN_WR_ACPI_FANS:
2133 case IBMACPI_FAN_WR_TPEC:
2134 if ((rc = fan_get_status(&s)) < 0)
2135 return rc;
2136
2137 /* Don't go out of emergency fan mode */
2138 if (s != 7)
2139 s = IBMACPI_FAN_EC_AUTO;
2140
2141 if (!acpi_ec_write(fan_status_offset, s))
2142 return -EIO;
2143 else
2144 fan_control_status_known = 1;
2145 break;
2146
2147 case IBMACPI_FAN_WR_ACPI_SFAN:
2148 if ((rc = fan_get_status(&s)) < 0)
2149 return rc;
2150
2151 s &= 0x07;
2152
2153 /* Set fan to at least level 4 */
2154 if (s < 4)
2155 s = 4;
2156
2157 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
2158 return -EIO;
2159 break;
2160
2161 default:
2162 return -ENXIO;
2163 }
2164 return 0;
2165}
2166
2167static int fan_set_disable(void)
2168{
2169 switch (fan_control_access_mode) {
2170 case IBMACPI_FAN_WR_ACPI_FANS:
2171 case IBMACPI_FAN_WR_TPEC:
2172 if (!acpi_ec_write(fan_status_offset, 0x00))
2173 return -EIO;
2174 else
2175 fan_control_status_known = 1;
2176 break;
2177
2178 case IBMACPI_FAN_WR_ACPI_SFAN:
2179 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
2180 return -EIO;
2181 break;
2182
2183 default:
2184 return -ENXIO;
2185 }
2186 return 0;
2187}
2188
2189static int fan_set_speed(int speed)
2190{
2191 switch (fan_control_access_mode) {
2192 case IBMACPI_FAN_WR_ACPI_FANS:
2193 if (speed >= 0 && speed <= 65535) {
2194 if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
2195 speed, speed, speed))
2196 return -EIO;
2197 } else
2198 return -EINVAL;
2199 break;
2200
2201 default:
2202 return -ENXIO;
2203 }
2204 return 0;
2205}
2206
2207static int fan_write_cmd_level(const char *cmd, int *rc)
2208{
2209 int level;
2210
2211 if (strlencmp(cmd, "level auto") == 0)
2212 level = IBMACPI_FAN_EC_AUTO;
2213 else if (strlencmp(cmd, "level disengaged") == 0)
2214 level = IBMACPI_FAN_EC_DISENGAGED;
2215 else if (sscanf(cmd, "level %d", &level) != 1)
2216 return 0;
2217
2218 if ((*rc = fan_set_level(level)) == -ENXIO)
2219 printk(IBM_ERR "level command accepted for unsupported "
2220 "access mode %d", fan_control_access_mode);
2221
2222 return 1;
2223}
2224
2225static int fan_write_cmd_enable(const char *cmd, int *rc)
2226{
2227 if (strlencmp(cmd, "enable") != 0)
2228 return 0;
2229
2230 if ((*rc = fan_set_enable()) == -ENXIO)
2231 printk(IBM_ERR "enable command accepted for unsupported "
2232 "access mode %d", fan_control_access_mode);
2233
2234 return 1;
2235}
2236
2237static int fan_write_cmd_disable(const char *cmd, int *rc)
2238{
2239 if (strlencmp(cmd, "disable") != 0)
2240 return 0;
2241
2242 if ((*rc = fan_set_disable()) == -ENXIO)
2243 printk(IBM_ERR "disable command accepted for unsupported "
2244 "access mode %d", fan_control_access_mode);
2245
2246 return 1;
2247}
2248
2249static int fan_write_cmd_speed(const char *cmd, int *rc)
2250{
2251 int speed;
2252
2253 /* TODO:
2254 * Support speed <low> <medium> <high> ? */
2255
2256 if (sscanf(cmd, "speed %d", &speed) != 1)
2257 return 0;
2258
2259 if ((*rc = fan_set_speed(speed)) == -ENXIO)
2260 printk(IBM_ERR "speed command accepted for unsupported "
2261 "access mode %d", fan_control_access_mode);
2262
2263 return 1;
2264}
2265
2266static int fan_write_cmd_watchdog(const char *cmd, int *rc)
2267{
2268 int interval;
2269
2270 if (sscanf(cmd, "watchdog %d", &interval) != 1)
2271 return 0;
2272
2273 if (interval < 0 || interval > 120)
2274 *rc = -EINVAL;
2275 else
2276 fan_watchdog_maxinterval = interval;
2277
2278 return 1;
2279}
2280
2281static int fan_write(char *buf)
2282{
2283 char *cmd;
2284 int rc = 0;
2285
2286 while (!rc && (cmd = next_cmd(&buf))) {
2287 if (!((fan_control_commands & IBMACPI_FAN_CMD_LEVEL) &&
2288 fan_write_cmd_level(cmd, &rc)) &&
2289 !((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) &&
2290 (fan_write_cmd_enable(cmd, &rc) ||
2291 fan_write_cmd_disable(cmd, &rc) ||
2292 fan_write_cmd_watchdog(cmd, &rc))) &&
2293 !((fan_control_commands & IBMACPI_FAN_CMD_SPEED) &&
2294 fan_write_cmd_speed(cmd, &rc))
2295 )
2296 rc = -EINVAL;
2297 else if (!rc)
2298 fan_watchdog_reset();
2299 }
2300
2301 return rc;
2302}
2303
2304static void fan_watchdog_fire(struct work_struct *ignored)
2305{
2306 printk(IBM_NOTICE "fan watchdog: enabling fan\n");
2307 if (fan_set_enable()) {
2308 printk(IBM_ERR "fan watchdog: error while enabling fan\n");
2309 /* reschedule for later */
2310 fan_watchdog_reset();
2311 }
2312}
2313
2314static struct ibm_struct ibms[] = {
2315 {
2316 .name = "driver",
2317 .init = ibm_acpi_driver_init,
2318 .read = driver_read,
2319 },
2320 {
2321 .name = "hotkey",
2322 .hid = IBM_HKEY_HID,
2323 .init = hotkey_init,
2324 .read = hotkey_read,
2325 .write = hotkey_write,
2326 .exit = hotkey_exit,
2327 .notify = hotkey_notify,
2328 .handle = &hkey_handle,
2329 .type = ACPI_DEVICE_NOTIFY,
2330 },
2331 {
2332 .name = "bluetooth",
2333 .init = bluetooth_init,
2334 .read = bluetooth_read,
2335 .write = bluetooth_write,
2336 },
2337 {
2338 .name = "wan",
2339 .init = wan_init,
2340 .read = wan_read,
2341 .write = wan_write,
2342 .experimental = 1,
2343 },
2344 {
2345 .name = "video",
2346 .init = video_init,
2347 .read = video_read,
2348 .write = video_write,
2349 .exit = video_exit,
2350 },
2351 {
2352 .name = "light",
2353 .init = light_init,
2354 .read = light_read,
2355 .write = light_write,
2356 },
2357#ifdef CONFIG_ACPI_IBM_DOCK
2358 {
2359 .name = "dock",
2360 .read = dock_read,
2361 .write = dock_write,
2362 .notify = dock_notify,
2363 .handle = &dock_handle,
2364 .type = ACPI_SYSTEM_NOTIFY,
2365 },
2366 {
2367 .name = "dock",
2368 .hid = IBM_PCI_HID,
2369 .notify = dock_notify,
2370 .handle = &pci_handle,
2371 .type = ACPI_SYSTEM_NOTIFY,
2372 },
2373#endif
2374#ifdef CONFIG_ACPI_IBM_BAY
2375 {
2376 .name = "bay",
2377 .init = bay_init,
2378 .read = bay_read,
2379 .write = bay_write,
2380 .notify = bay_notify,
2381 .handle = &bay_handle,
2382 .type = ACPI_SYSTEM_NOTIFY,
2383 },
2384#endif /* CONFIG_ACPI_IBM_BAY */
2385 {
2386 .name = "cmos",
2387 .read = cmos_read,
2388 .write = cmos_write,
2389 },
2390 {
2391 .name = "led",
2392 .init = led_init,
2393 .read = led_read,
2394 .write = led_write,
2395 },
2396 {
2397 .name = "beep",
2398 .read = beep_read,
2399 .write = beep_write,
2400 },
2401 {
2402 .name = "thermal",
2403 .init = thermal_init,
2404 .read = thermal_read,
2405 },
2406 {
2407 .name = "ecdump",
2408 .read = ecdump_read,
2409 .write = ecdump_write,
2410 .experimental = 1,
2411 },
2412 {
2413 .name = "brightness",
2414 .read = brightness_read,
2415 .write = brightness_write,
2416 .init = brightness_init,
2417 .exit = brightness_exit,
2418 },
2419 {
2420 .name = "volume",
2421 .read = volume_read,
2422 .write = volume_write,
2423 },
2424 {
2425 .name = "fan",
2426 .read = fan_read,
2427 .write = fan_write,
2428 .init = fan_init,
2429 .exit = fan_exit,
2430 .experimental = 1,
2431 },
2432};
2433
2434static int dispatch_read(char *page, char **start, off_t off, int count,
2435 int *eof, void *data)
2436{
2437 struct ibm_struct *ibm = data;
2438 int len;
2439
2440 if (!ibm || !ibm->read)
2441 return -EINVAL;
2442
2443 len = ibm->read(page);
2444 if (len < 0)
2445 return len;
2446
2447 if (len <= off + count)
2448 *eof = 1;
2449 *start = page + off;
2450 len -= off;
2451 if (len > count)
2452 len = count;
2453 if (len < 0)
2454 len = 0;
2455
2456 return len;
2457}
2458
2459static int dispatch_write(struct file *file, const char __user * userbuf,
2460 unsigned long count, void *data)
2461{
2462 struct ibm_struct *ibm = data;
2463 char *kernbuf;
2464 int ret;
2465
2466 if (!ibm || !ibm->write)
2467 return -EINVAL;
2468
2469 kernbuf = kmalloc(count + 2, GFP_KERNEL);
2470 if (!kernbuf)
2471 return -ENOMEM;
2472
2473 if (copy_from_user(kernbuf, userbuf, count)) {
2474 kfree(kernbuf);
2475 return -EFAULT;
2476 }
2477
2478 kernbuf[count] = 0;
2479 strcat(kernbuf, ",");
2480 ret = ibm->write(kernbuf);
2481 if (ret == 0)
2482 ret = count;
2483
2484 kfree(kernbuf);
2485
2486 return ret;
2487}
2488
2489static void dispatch_notify(acpi_handle handle, u32 event, void *data)
2490{
2491 struct ibm_struct *ibm = data;
2492
2493 if (!ibm || !ibm->notify)
2494 return;
2495
2496 ibm->notify(ibm, event);
2497}
2498
2499static int __init setup_notify(struct ibm_struct *ibm)
2500{
2501 acpi_status status;
2502 int ret;
2503
2504 if (!*ibm->handle)
2505 return 0;
2506
2507 ret = acpi_bus_get_device(*ibm->handle, &ibm->device);
2508 if (ret < 0) {
2509 printk(IBM_ERR "%s device not present\n", ibm->name);
2510 return -ENODEV;
2511 }
2512
2513 acpi_driver_data(ibm->device) = ibm;
2514 sprintf(acpi_device_class(ibm->device), "%s/%s", IBM_NAME, ibm->name);
2515
2516 status = acpi_install_notify_handler(*ibm->handle, ibm->type,
2517 dispatch_notify, ibm);
2518 if (ACPI_FAILURE(status)) {
2519 if (status == AE_ALREADY_EXISTS) {
2520 printk(IBM_NOTICE "another device driver is already handling %s events\n",
2521 ibm->name);
2522 } else {
2523 printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
2524 ibm->name, status);
2525 }
2526 return -ENODEV;
2527 }
2528 ibm->notify_installed = 1;
2529 return 0;
2530}
2531
2532static int __init ibm_device_add(struct acpi_device *device)
2533{
2534 return 0;
2535}
2536
2537static int __init register_driver(struct ibm_struct *ibm)
2538{
2539 int ret;
2540
2541 ibm->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
2542 if (!ibm->driver) {
2543 printk(IBM_ERR "kmalloc(ibm->driver) failed\n");
2544 return -1;
2545 }
2546
2547 sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name);
2548 ibm->driver->ids = ibm->hid;
2549 ibm->driver->ops.add = &ibm_device_add;
2550
2551 ret = acpi_bus_register_driver(ibm->driver);
2552 if (ret < 0) {
2553 printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
2554 ibm->hid, ret);
2555 kfree(ibm->driver);
2556 }
2557
2558 return ret;
2559}
2560
2561static void ibm_exit(struct ibm_struct *ibm);
2562
2563static int __init ibm_init(struct ibm_struct *ibm)
2564{
2565 int ret;
2566 struct proc_dir_entry *entry;
2567
2568 if (ibm->experimental && !experimental)
2569 return 0;
2570
2571 if (ibm->hid) {
2572 ret = register_driver(ibm);
2573 if (ret < 0)
2574 return ret;
2575 ibm->driver_registered = 1;
2576 }
2577
2578 if (ibm->init) {
2579 ret = ibm->init();
2580 if (ret != 0)
2581 return ret;
2582 ibm->init_called = 1;
2583 }
2584
2585 if (ibm->read) {
2586 entry = create_proc_entry(ibm->name,
2587 S_IFREG | S_IRUGO | S_IWUSR,
2588 proc_dir);
2589 if (!entry) {
2590 printk(IBM_ERR "unable to create proc entry %s\n",
2591 ibm->name);
2592 return -ENODEV;
2593 }
2594 entry->owner = THIS_MODULE;
2595 entry->data = ibm;
2596 entry->read_proc = &dispatch_read;
2597 if (ibm->write)
2598 entry->write_proc = &dispatch_write;
2599 ibm->proc_created = 1;
2600 }
2601
2602 if (ibm->notify) {
2603 ret = setup_notify(ibm);
2604 if (ret == -ENODEV) {
2605 printk(IBM_NOTICE "disabling subdriver %s\n",
2606 ibm->name);
2607 ibm_exit(ibm);
2608 return 0;
2609 }
2610 if (ret < 0)
2611 return ret;
2612 }
2613
2614 return 0;
2615}
2616
2617static void ibm_exit(struct ibm_struct *ibm)
2618{
2619 if (ibm->notify_installed)
2620 acpi_remove_notify_handler(*ibm->handle, ibm->type,
2621 dispatch_notify);
2622
2623 if (ibm->proc_created)
2624 remove_proc_entry(ibm->name, proc_dir);
2625
2626 if (ibm->init_called && ibm->exit)
2627 ibm->exit();
2628
2629 if (ibm->driver_registered) {
2630 acpi_bus_unregister_driver(ibm->driver);
2631 kfree(ibm->driver);
2632 }
2633}
2634
2635static void __init ibm_handle_init(char *name,
2636 acpi_handle * handle, acpi_handle parent,
2637 char **paths, int num_paths, char **path)
2638{
2639 int i;
2640 acpi_status status;
2641
2642 for (i = 0; i < num_paths; i++) {
2643 status = acpi_get_handle(parent, paths[i], handle);
2644 if (ACPI_SUCCESS(status)) {
2645 *path = paths[i];
2646 return;
2647 }
2648 }
2649
2650 *handle = NULL;
2651}
2652
2653#define IBM_HANDLE_INIT(object) \
2654 ibm_handle_init(#object, &object##_handle, *object##_parent, \
2655 object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
2656
2657static int __init set_ibm_param(const char *val, struct kernel_param *kp)
2658{
2659 unsigned int i;
2660
2661 for (i = 0; i < ARRAY_SIZE(ibms); i++)
2662 if (strcmp(ibms[i].name, kp->name) == 0 && ibms[i].write) {
2663 if (strlen(val) > sizeof(ibms[i].param) - 2)
2664 return -ENOSPC;
2665 strcpy(ibms[i].param, val);
2666 strcat(ibms[i].param, ",");
2667 return 0;
2668 }
2669
2670 return -EINVAL;
2671}
2672
2673#define IBM_PARAM(feature) \
2674 module_param_call(feature, set_ibm_param, NULL, NULL, 0)
2675
2676IBM_PARAM(hotkey);
2677IBM_PARAM(bluetooth);
2678IBM_PARAM(video);
2679IBM_PARAM(light);
2680#ifdef CONFIG_ACPI_IBM_DOCK
2681IBM_PARAM(dock);
2682#endif
2683#ifdef CONFIG_ACPI_IBM_BAY
2684IBM_PARAM(bay);
2685#endif /* CONFIG_ACPI_IBM_BAY */
2686IBM_PARAM(cmos);
2687IBM_PARAM(led);
2688IBM_PARAM(beep);
2689IBM_PARAM(ecdump);
2690IBM_PARAM(brightness);
2691IBM_PARAM(volume);
2692IBM_PARAM(fan);
2693
2694static void acpi_ibm_exit(void)
2695{
2696 int i;
2697
2698 for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
2699 ibm_exit(&ibms[i]);
2700
2701 if (proc_dir)
2702 remove_proc_entry(IBM_DIR, acpi_root_dir);
2703
2704 if (ibm_thinkpad_ec_found)
2705 kfree(ibm_thinkpad_ec_found);
2706}
2707
2708static char* __init check_dmi_for_ec(void)
2709{
2710 struct dmi_device *dev = NULL;
2711 char ec_fw_string[18];
2712
2713 /*
2714 * ThinkPad T23 or newer, A31 or newer, R50e or newer,
2715 * X32 or newer, all Z series; Some models must have an
2716 * up-to-date BIOS or they will not be detected.
2717 *
2718 * See http://thinkwiki.org/wiki/List_of_DMI_IDs
2719 */
2720 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
2721 if (sscanf(dev->name,
2722 "IBM ThinkPad Embedded Controller -[%17c",
2723 ec_fw_string) == 1) {
2724 ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
2725 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
2726 return kstrdup(ec_fw_string, GFP_KERNEL);
2727 }
2728 }
2729 return NULL;
2730}
2731
2732static int __init acpi_ibm_init(void)
2733{
2734 int ret, i;
2735
2736 if (acpi_disabled)
2737 return -ENODEV;
2738
2739 /* ec is required because many other handles are relative to it */
2740 IBM_HANDLE_INIT(ec);
2741 if (!ec_handle) {
2742 printk(IBM_ERR "ec object not found\n");
2743 return -ENODEV;
2744 }
2745
2746 /* Models with newer firmware report the EC in DMI */
2747 ibm_thinkpad_ec_found = check_dmi_for_ec();
2748
2749 /* these handles are not required */
2750 IBM_HANDLE_INIT(vid);
2751 IBM_HANDLE_INIT(vid2);
2752 IBM_HANDLE_INIT(ledb);
2753 IBM_HANDLE_INIT(led);
2754 IBM_HANDLE_INIT(hkey);
2755 IBM_HANDLE_INIT(lght);
2756 IBM_HANDLE_INIT(cmos);
2757#ifdef CONFIG_ACPI_IBM_DOCK
2758 IBM_HANDLE_INIT(dock);
2759#endif
2760 IBM_HANDLE_INIT(pci);
2761#ifdef CONFIG_ACPI_IBM_BAY
2762 IBM_HANDLE_INIT(bay);
2763 if (bay_handle)
2764 IBM_HANDLE_INIT(bay_ej);
2765 IBM_HANDLE_INIT(bay2);
2766 if (bay2_handle)
2767 IBM_HANDLE_INIT(bay2_ej);
2768#endif /* CONFIG_ACPI_IBM_BAY */
2769 IBM_HANDLE_INIT(beep);
2770 IBM_HANDLE_INIT(ecrd);
2771 IBM_HANDLE_INIT(ecwr);
2772 IBM_HANDLE_INIT(fans);
2773 IBM_HANDLE_INIT(gfan);
2774 IBM_HANDLE_INIT(sfan);
2775
2776 proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
2777 if (!proc_dir) {
2778 printk(IBM_ERR "unable to create proc dir %s", IBM_DIR);
2779 acpi_ibm_exit();
2780 return -ENODEV;
2781 }
2782 proc_dir->owner = THIS_MODULE;
2783
2784 for (i = 0; i < ARRAY_SIZE(ibms); i++) {
2785 ret = ibm_init(&ibms[i]);
2786 if (ret >= 0 && *ibms[i].param)
2787 ret = ibms[i].write(ibms[i].param);
2788 if (ret < 0) {
2789 acpi_ibm_exit();
2790 return ret;
2791 }
2792 }
2793
2794 return 0;
2795}
2796
2797module_init(acpi_ibm_init);
2798module_exit(acpi_ibm_exit);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 99d1516d1e70..f7de02a6f497 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -70,8 +70,6 @@
70#define ACPI_PROCESSOR_LIMIT_USER 0 70#define ACPI_PROCESSOR_LIMIT_USER 0
71#define ACPI_PROCESSOR_LIMIT_THERMAL 1 71#define ACPI_PROCESSOR_LIMIT_THERMAL 1
72 72
73#define ACPI_STA_PRESENT 0x00000001
74
75#define _COMPONENT ACPI_PROCESSOR_COMPONENT 73#define _COMPONENT ACPI_PROCESSOR_COMPONENT
76ACPI_MODULE_NAME("processor_core"); 74ACPI_MODULE_NAME("processor_core");
77 75
@@ -779,7 +777,7 @@ static int is_processor_present(acpi_handle handle)
779 777
780 778
781 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); 779 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
782 if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) { 780 if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) {
783 ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); 781 ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
784 return 0; 782 return 0;
785 } 783 }
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index cdf78943af4d..ae0654cd11ea 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -51,14 +51,6 @@
51#include <asm/apic.h> 51#include <asm/apic.h>
52#endif 52#endif
53 53
54/*
55 * Include the apic definitions for x86 to have the APIC timer related defines
56 * available also for UP (on SMP it gets magically included via linux/smp.h).
57 */
58#ifdef CONFIG_X86
59#include <asm/apic.h>
60#endif
61
62#include <asm/io.h> 54#include <asm/io.h>
63#include <asm/uaccess.h> 55#include <asm/uaccess.h>
64 56
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 59640d9a0acc..c1bae106833c 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -30,30 +30,10 @@
30#include <linux/seq_file.h> 30#include <linux/seq_file.h>
31#include <asm/uaccess.h> 31#include <asm/uaccess.h>
32#include <linux/acpi.h> 32#include <linux/acpi.h>
33#include <linux/i2c.h> 33#include <linux/timer.h>
34#include <linux/jiffies.h>
34#include <linux/delay.h> 35#include <linux/delay.h>
35 36
36#include "i2c_ec.h"
37
38#define DEF_CAPACITY_UNIT 3
39#define MAH_CAPACITY_UNIT 1
40#define MWH_CAPACITY_UNIT 2
41#define CAPACITY_UNIT DEF_CAPACITY_UNIT
42
43#define REQUEST_UPDATE_MODE 1
44#define QUEUE_UPDATE_MODE 2
45
46#define DATA_TYPE_COMMON 0
47#define DATA_TYPE_INFO 1
48#define DATA_TYPE_STATE 2
49#define DATA_TYPE_ALARM 3
50#define DATA_TYPE_AC_STATE 4
51
52extern struct proc_dir_entry *acpi_lock_ac_dir(void);
53extern struct proc_dir_entry *acpi_lock_battery_dir(void);
54extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
55extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
56
57#define ACPI_SBS_COMPONENT 0x00080000 37#define ACPI_SBS_COMPONENT 0x00080000
58#define ACPI_SBS_CLASS "sbs" 38#define ACPI_SBS_CLASS "sbs"
59#define ACPI_AC_CLASS "ac_adapter" 39#define ACPI_AC_CLASS "ac_adapter"
@@ -74,39 +54,75 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
74 54
75#define _COMPONENT ACPI_SBS_COMPONENT 55#define _COMPONENT ACPI_SBS_COMPONENT
76 56
77#define MAX_SBS_BAT 4
78#define MAX_SMBUS_ERR 1
79
80ACPI_MODULE_NAME("sbs"); 57ACPI_MODULE_NAME("sbs");
81 58
82MODULE_AUTHOR("Rich Townsend"); 59MODULE_AUTHOR("Rich Townsend");
83MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); 60MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
84MODULE_LICENSE("GPL"); 61MODULE_LICENSE("GPL");
85 62
86static struct semaphore sbs_sem; 63#define xmsleep(t) msleep(t)
64
65#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */
66
67#define ACPI_EC_SMB_STS 0x01 /* status */
68#define ACPI_EC_SMB_ADDR 0x02 /* address */
69#define ACPI_EC_SMB_CMD 0x03 /* command */
70#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */
71#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */
87 72
88#define UPDATE_MODE QUEUE_UPDATE_MODE 73#define ACPI_EC_SMB_STS_DONE 0x80
89/* REQUEST_UPDATE_MODE QUEUE_UPDATE_MODE */ 74#define ACPI_EC_SMB_STS_STATUS 0x1f
90#define UPDATE_INFO_MODE 0
91#define UPDATE_TIME 60
92#define UPDATE_TIME2 0
93 75
94static int capacity_mode = CAPACITY_UNIT; 76#define ACPI_EC_SMB_PRTCL_WRITE 0x00
95static int update_mode = UPDATE_MODE; 77#define ACPI_EC_SMB_PRTCL_READ 0x01
96static int update_info_mode = UPDATE_INFO_MODE; 78#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
97static int update_time = UPDATE_TIME; 79#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
98static int update_time2 = UPDATE_TIME2;
99 80
100module_param(capacity_mode, int, 0); 81#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
101module_param(update_mode, int, 0); 82#define ACPI_EC_SMB_ACCESS_SLEEP1 1
102module_param(update_info_mode, int, 0); 83#define ACPI_EC_SMB_ACCESS_SLEEP2 10
103module_param(update_time, int, 0); 84
104module_param(update_time2, int, 0); 85#define DEF_CAPACITY_UNIT 3
86#define MAH_CAPACITY_UNIT 1
87#define MWH_CAPACITY_UNIT 2
88#define CAPACITY_UNIT DEF_CAPACITY_UNIT
89
90#define REQUEST_UPDATE_MODE 1
91#define QUEUE_UPDATE_MODE 2
92
93#define DATA_TYPE_COMMON 0
94#define DATA_TYPE_INFO 1
95#define DATA_TYPE_STATE 2
96#define DATA_TYPE_ALARM 3
97#define DATA_TYPE_AC_STATE 4
98
99extern struct proc_dir_entry *acpi_lock_ac_dir(void);
100extern struct proc_dir_entry *acpi_lock_battery_dir(void);
101extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
102extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
103
104#define MAX_SBS_BAT 4
105#define ACPI_SBS_BLOCK_MAX 32
106
107#define ACPI_SBS_SMBUS_READ 1
108#define ACPI_SBS_SMBUS_WRITE 2
109
110#define ACPI_SBS_WORD_DATA 1
111#define ACPI_SBS_BLOCK_DATA 2
112
113#define UPDATE_DELAY 10
114
115/* 0 - every time, > 0 - by update_time */
116static unsigned int update_time = 120;
117
118static unsigned int capacity_mode = CAPACITY_UNIT;
119
120module_param(update_time, uint, 0644);
121module_param(capacity_mode, uint, 0444);
105 122
106static int acpi_sbs_add(struct acpi_device *device); 123static int acpi_sbs_add(struct acpi_device *device);
107static int acpi_sbs_remove(struct acpi_device *device, int type); 124static int acpi_sbs_remove(struct acpi_device *device, int type);
108static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus); 125static int acpi_sbs_resume(struct acpi_device *device);
109static void acpi_sbs_update_queue(void *data);
110 126
111static struct acpi_driver acpi_sbs_driver = { 127static struct acpi_driver acpi_sbs_driver = {
112 .name = "sbs", 128 .name = "sbs",
@@ -115,9 +131,14 @@ static struct acpi_driver acpi_sbs_driver = {
115 .ops = { 131 .ops = {
116 .add = acpi_sbs_add, 132 .add = acpi_sbs_add,
117 .remove = acpi_sbs_remove, 133 .remove = acpi_sbs_remove,
134 .resume = acpi_sbs_resume,
118 }, 135 },
119}; 136};
120 137
138struct acpi_ac {
139 int ac_present;
140};
141
121struct acpi_battery_info { 142struct acpi_battery_info {
122 int capacity_mode; 143 int capacity_mode;
123 s16 full_charge_capacity; 144 s16 full_charge_capacity;
@@ -126,18 +147,16 @@ struct acpi_battery_info {
126 int vscale; 147 int vscale;
127 int ipscale; 148 int ipscale;
128 s16 serial_number; 149 s16 serial_number;
129 char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3]; 150 char manufacturer_name[ACPI_SBS_BLOCK_MAX + 3];
130 char device_name[I2C_SMBUS_BLOCK_MAX + 3]; 151 char device_name[ACPI_SBS_BLOCK_MAX + 3];
131 char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3]; 152 char device_chemistry[ACPI_SBS_BLOCK_MAX + 3];
132}; 153};
133 154
134struct acpi_battery_state { 155struct acpi_battery_state {
135 s16 voltage; 156 s16 voltage;
136 s16 amperage; 157 s16 amperage;
137 s16 remaining_capacity; 158 s16 remaining_capacity;
138 s16 average_time_to_empty; 159 s16 battery_state;
139 s16 average_time_to_full;
140 s16 battery_status;
141}; 160};
142 161
143struct acpi_battery_alarm { 162struct acpi_battery_alarm {
@@ -146,9 +165,9 @@ struct acpi_battery_alarm {
146 165
147struct acpi_battery { 166struct acpi_battery {
148 int alive; 167 int alive;
149 int battery_present;
150 int id; 168 int id;
151 int init_state; 169 int init_state;
170 int battery_present;
152 struct acpi_sbs *sbs; 171 struct acpi_sbs *sbs;
153 struct acpi_battery_info info; 172 struct acpi_battery_info info;
154 struct acpi_battery_state state; 173 struct acpi_battery_state state;
@@ -158,186 +177,251 @@ struct acpi_battery {
158 177
159struct acpi_sbs { 178struct acpi_sbs {
160 acpi_handle handle; 179 acpi_handle handle;
180 int base;
161 struct acpi_device *device; 181 struct acpi_device *device;
162 struct acpi_ec_smbus *smbus; 182 struct acpi_ec_smbus *smbus;
183 struct mutex mutex;
163 int sbsm_present; 184 int sbsm_present;
164 int sbsm_batteries_supported; 185 int sbsm_batteries_supported;
165 int ac_present;
166 struct proc_dir_entry *ac_entry; 186 struct proc_dir_entry *ac_entry;
187 struct acpi_ac ac;
167 struct acpi_battery battery[MAX_SBS_BAT]; 188 struct acpi_battery battery[MAX_SBS_BAT];
168 int update_info_mode;
169 int zombie; 189 int zombie;
170 int update_time;
171 int update_time2;
172 struct timer_list update_timer; 190 struct timer_list update_timer;
191 int run_cnt;
192 int update_proc_flg;
173}; 193};
174 194
175static void acpi_update_delay(struct acpi_sbs *sbs); 195static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type);
176static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type); 196static void acpi_sbs_update_time(void *data);
197
198union sbs_rw_data {
199 u16 word;
200 u8 block[ACPI_SBS_BLOCK_MAX + 2];
201};
202
203static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
204 char read_write, u8 command, int size,
205 union sbs_rw_data *data);
177 206
178/* -------------------------------------------------------------------------- 207/* --------------------------------------------------------------------------
179 SMBus Communication 208 SMBus Communication
180 -------------------------------------------------------------------------- */ 209 -------------------------------------------------------------------------- */
181 210
182static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus) 211static int acpi_ec_sbs_read(struct acpi_sbs *sbs, u8 address, u8 * data)
183{ 212{
184 union i2c_smbus_data data; 213 u8 val;
185 int result = 0; 214 int err;
186 char *err_str;
187 int err_number;
188 215
189 data.word = 0; 216 err = ec_read(sbs->base + address, &val);
217 if (!err) {
218 *data = val;
219 }
220 xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
221 return (err);
222}
190 223
191 result = smbus->adapter.algo-> 224static int acpi_ec_sbs_write(struct acpi_sbs *sbs, u8 address, u8 data)
192 smbus_xfer(&smbus->adapter, 225{
193 ACPI_SB_SMBUS_ADDR, 226 int err;
194 0, I2C_SMBUS_READ, 0x16, I2C_SMBUS_BLOCK_DATA, &data);
195 227
196 err_number = (data.word & 0x000f); 228 err = ec_write(sbs->base + address, data);
229 return (err);
230}
197 231
198 switch (data.word & 0x000f) { 232static int
199 case 0x0000: 233acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
200 err_str = "unexpected bus error"; 234 char read_write, u8 command, int size,
201 break; 235 union sbs_rw_data *data)
202 case 0x0001: 236{
203 err_str = "busy"; 237 unsigned char protocol, len = 0, temp[2] = { 0, 0 };
204 break; 238 int i;
205 case 0x0002: 239
206 err_str = "reserved command"; 240 if (read_write == ACPI_SBS_SMBUS_READ) {
207 break; 241 protocol = ACPI_EC_SMB_PRTCL_READ;
208 case 0x0003: 242 } else {
209 err_str = "unsupported command"; 243 protocol = ACPI_EC_SMB_PRTCL_WRITE;
210 break; 244 }
211 case 0x0004: 245
212 err_str = "access denied"; 246 switch (size) {
247
248 case ACPI_SBS_WORD_DATA:
249 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
250 if (read_write == ACPI_SBS_SMBUS_WRITE) {
251 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA, data->word);
252 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + 1,
253 data->word >> 8);
254 }
255 protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA;
213 break; 256 break;
214 case 0x0005: 257 case ACPI_SBS_BLOCK_DATA:
215 err_str = "overflow/underflow"; 258 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
259 if (read_write == ACPI_SBS_SMBUS_WRITE) {
260 len = min_t(u8, data->block[0], 32);
261 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_BCNT, len);
262 for (i = 0; i < len; i++)
263 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + i,
264 data->block[i + 1]);
265 }
266 protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA;
216 break; 267 break;
217 case 0x0006: 268 default:
218 err_str = "bad size"; 269 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
270 "unsupported transaction %d", size));
271 return (-1);
272 }
273
274 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_ADDR, addr << 1);
275 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_PRTCL, protocol);
276
277 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
278
279 if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
280 xmsleep(ACPI_EC_SMB_ACCESS_SLEEP1);
281 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
282 }
283 if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
284 xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
285 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
286 }
287 if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
288 || (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
289 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
290 "transaction %d error", size));
291 return (-1);
292 }
293
294 if (read_write == ACPI_SBS_SMBUS_WRITE) {
295 return (0);
296 }
297
298 switch (size) {
299
300 case ACPI_SBS_WORD_DATA:
301 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA, temp);
302 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + 1, temp + 1);
303 data->word = (temp[1] << 8) | temp[0];
219 break; 304 break;
220 case 0x0007: 305
221 err_str = "unknown error"; 306 case ACPI_SBS_BLOCK_DATA:
307 len = 0;
308 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_BCNT, &len);
309 len = min_t(u8, len, 32);
310 for (i = 0; i < len; i++)
311 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + i,
312 data->block + i + 1);
313 data->block[0] = len;
222 break; 314 break;
223 default: 315 default:
224 err_str = "unrecognized error"; 316 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
317 "unsupported transaction %d", size));
318 return (-1);
225 } 319 }
226 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 320
227 "%s: ret %i, err %i\n", err_str, result, err_number)); 321 return (0);
228} 322}
229 323
230static int 324static int
231acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, int addr, int func, 325acpi_sbs_read_word(struct acpi_sbs *sbs, int addr, int func, u16 * word)
232 u16 * word,
233 void (*err_handler) (struct acpi_ec_smbus * smbus))
234{ 326{
235 union i2c_smbus_data data; 327 union sbs_rw_data data;
236 int result = 0; 328 int result = 0;
237 int i;
238 329
239 if (err_handler == NULL) { 330 result = acpi_ec_sbs_access(sbs, addr,
240 err_handler = acpi_battery_smbus_err_handler; 331 ACPI_SBS_SMBUS_READ, func,
241 } 332 ACPI_SBS_WORD_DATA, &data);
242 333 if (result) {
243 for (i = 0; i < MAX_SMBUS_ERR; i++) { 334 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
244 result = 335 "acpi_ec_sbs_access() failed"));
245 smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, 336 } else {
246 I2C_SMBUS_READ, func, 337 *word = data.word;
247 I2C_SMBUS_WORD_DATA, &data);
248 if (result) {
249 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
250 "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
251 i));
252 if (err_handler) {
253 err_handler(smbus);
254 }
255 } else {
256 *word = data.word;
257 break;
258 }
259 } 338 }
260 339
261 return result; 340 return result;
262} 341}
263 342
264static int 343static int
265acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, int addr, int func, 344acpi_sbs_read_str(struct acpi_sbs *sbs, int addr, int func, char *str)
266 char *str,
267 void (*err_handler) (struct acpi_ec_smbus * smbus))
268{ 345{
269 union i2c_smbus_data data; 346 union sbs_rw_data data;
270 int result = 0; 347 int result = 0;
271 int i;
272
273 if (err_handler == NULL) {
274 err_handler = acpi_battery_smbus_err_handler;
275 }
276 348
277 for (i = 0; i < MAX_SMBUS_ERR; i++) { 349 result = acpi_ec_sbs_access(sbs, addr,
278 result = 350 ACPI_SBS_SMBUS_READ, func,
279 smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, 351 ACPI_SBS_BLOCK_DATA, &data);
280 I2C_SMBUS_READ, func, 352 if (result) {
281 I2C_SMBUS_BLOCK_DATA, 353 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
282 &data); 354 "acpi_ec_sbs_access() failed"));
283 if (result) { 355 } else {
284 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 356 strncpy(str, (const char *)data.block + 1, data.block[0]);
285 "try %i: smbus->adapter.algo->smbus_xfer() failed\n", 357 str[data.block[0]] = 0;
286 i));
287 if (err_handler) {
288 err_handler(smbus);
289 }
290 } else {
291 strncpy(str, (const char *)data.block + 1,
292 data.block[0]);
293 str[data.block[0]] = 0;
294 break;
295 }
296 } 358 }
297 359
298 return result; 360 return result;
299} 361}
300 362
301static int 363static int
302acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, int addr, int func, 364acpi_sbs_write_word(struct acpi_sbs *sbs, int addr, int func, int word)
303 int word,
304 void (*err_handler) (struct acpi_ec_smbus * smbus))
305{ 365{
306 union i2c_smbus_data data; 366 union sbs_rw_data data;
307 int result = 0; 367 int result = 0;
308 int i;
309
310 if (err_handler == NULL) {
311 err_handler = acpi_battery_smbus_err_handler;
312 }
313 368
314 data.word = word; 369 data.word = word;
315 370
316 for (i = 0; i < MAX_SMBUS_ERR; i++) { 371 result = acpi_ec_sbs_access(sbs, addr,
317 result = 372 ACPI_SBS_SMBUS_WRITE, func,
318 smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, 373 ACPI_SBS_WORD_DATA, &data);
319 I2C_SMBUS_WRITE, func, 374 if (result) {
320 I2C_SMBUS_WORD_DATA, &data); 375 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
321 if (result) { 376 "acpi_ec_sbs_access() failed"));
322 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
323 "try %i: smbus->adapter.algo"
324 "->smbus_xfer() failed\n", i));
325 if (err_handler) {
326 err_handler(smbus);
327 }
328 } else {
329 break;
330 }
331 } 377 }
332 378
333 return result; 379 return result;
334} 380}
335 381
382static int sbs_zombie(struct acpi_sbs *sbs)
383{
384 return (sbs->zombie);
385}
386
387static int sbs_mutex_lock(struct acpi_sbs *sbs)
388{
389 if (sbs_zombie(sbs)) {
390 return -ENODEV;
391 }
392 mutex_lock(&sbs->mutex);
393 return 0;
394}
395
396static void sbs_mutex_unlock(struct acpi_sbs *sbs)
397{
398 mutex_unlock(&sbs->mutex);
399}
400
336/* -------------------------------------------------------------------------- 401/* --------------------------------------------------------------------------
337 Smart Battery System Management 402 Smart Battery System Management
338 -------------------------------------------------------------------------- */ 403 -------------------------------------------------------------------------- */
339 404
340/* Smart Battery */ 405static int acpi_check_update_proc(struct acpi_sbs *sbs)
406{
407 acpi_status status = AE_OK;
408
409 if (update_time == 0) {
410 sbs->update_proc_flg = 0;
411 return 0;
412 }
413 if (sbs->update_proc_flg == 0) {
414 status = acpi_os_execute(OSL_GPE_HANDLER,
415 acpi_sbs_update_time, sbs);
416 if (status != AE_OK) {
417 ACPI_EXCEPTION((AE_INFO, status,
418 "acpi_os_execute() failed"));
419 return 1;
420 }
421 sbs->update_proc_flg = 1;
422 }
423 return 0;
424}
341 425
342static int acpi_sbs_generate_event(struct acpi_device *device, 426static int acpi_sbs_generate_event(struct acpi_device *device,
343 int event, int state, char *bid, char *class) 427 int event, int state, char *bid, char *class)
@@ -366,12 +450,11 @@ static int acpi_battery_get_present(struct acpi_battery *battery)
366 int result = 0; 450 int result = 0;
367 int is_present = 0; 451 int is_present = 0;
368 452
369 result = acpi_sbs_smbus_read_word(battery->sbs->smbus, 453 result = acpi_sbs_read_word(battery->sbs,
370 ACPI_SBSM_SMBUS_ADDR, 0x01, 454 ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
371 &state, NULL);
372 if (result) { 455 if (result) {
373 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 456 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
374 "acpi_sbs_smbus_read_word() failed")); 457 "acpi_sbs_read_word() failed"));
375 } 458 }
376 if (!result) { 459 if (!result) {
377 is_present = (state & 0x000f) & (1 << battery->id); 460 is_present = (state & 0x000f) & (1 << battery->id);
@@ -381,45 +464,33 @@ static int acpi_battery_get_present(struct acpi_battery *battery)
381 return result; 464 return result;
382} 465}
383 466
384static int acpi_battery_is_present(struct acpi_battery *battery)
385{
386 return (battery->battery_present);
387}
388
389static int acpi_ac_is_present(struct acpi_sbs *sbs)
390{
391 return (sbs->ac_present);
392}
393
394static int acpi_battery_select(struct acpi_battery *battery) 467static int acpi_battery_select(struct acpi_battery *battery)
395{ 468{
396 struct acpi_ec_smbus *smbus = battery->sbs->smbus; 469 struct acpi_sbs *sbs = battery->sbs;
397 int result = 0; 470 int result = 0;
398 s16 state; 471 s16 state;
399 int foo; 472 int foo;
400 473
401 if (battery->sbs->sbsm_present) { 474 if (sbs->sbsm_present) {
402 475
403 /* Take special care not to knobble other nibbles of 476 /* Take special care not to knobble other nibbles of
404 * state (aka selector_state), since 477 * state (aka selector_state), since
405 * it causes charging to halt on SBSELs */ 478 * it causes charging to halt on SBSELs */
406 479
407 result = 480 result =
408 acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01, 481 acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
409 &state, NULL);
410 if (result) { 482 if (result) {
411 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 483 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
412 "acpi_sbs_smbus_read_word() failed\n")); 484 "acpi_sbs_read_word() failed"));
413 goto end; 485 goto end;
414 } 486 }
415 487
416 foo = (state & 0x0fff) | (1 << (battery->id + 12)); 488 foo = (state & 0x0fff) | (1 << (battery->id + 12));
417 result = 489 result =
418 acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01, 490 acpi_sbs_write_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, foo);
419 foo, NULL);
420 if (result) { 491 if (result) {
421 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 492 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
422 "acpi_sbs_smbus_write_word() failed\n")); 493 "acpi_sbs_write_word() failed"));
423 goto end; 494 goto end;
424 } 495 }
425 } 496 }
@@ -430,15 +501,14 @@ static int acpi_battery_select(struct acpi_battery *battery)
430 501
431static int acpi_sbsm_get_info(struct acpi_sbs *sbs) 502static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
432{ 503{
433 struct acpi_ec_smbus *smbus = sbs->smbus;
434 int result = 0; 504 int result = 0;
435 s16 battery_system_info; 505 s16 battery_system_info;
436 506
437 result = acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04, 507 result = acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x04,
438 &battery_system_info, NULL); 508 &battery_system_info);
439 if (result) { 509 if (result) {
440 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 510 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
441 "acpi_sbs_smbus_read_word() failed\n")); 511 "acpi_sbs_read_word() failed"));
442 goto end; 512 goto end;
443 } 513 }
444 514
@@ -451,53 +521,50 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
451 521
452static int acpi_battery_get_info(struct acpi_battery *battery) 522static int acpi_battery_get_info(struct acpi_battery *battery)
453{ 523{
454 struct acpi_ec_smbus *smbus = battery->sbs->smbus; 524 struct acpi_sbs *sbs = battery->sbs;
455 int result = 0; 525 int result = 0;
456 s16 battery_mode; 526 s16 battery_mode;
457 s16 specification_info; 527 s16 specification_info;
458 528
459 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03, 529 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03,
460 &battery_mode, 530 &battery_mode);
461 &acpi_battery_smbus_err_handler);
462 if (result) { 531 if (result) {
463 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 532 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
464 "acpi_sbs_smbus_read_word() failed\n")); 533 "acpi_sbs_read_word() failed"));
465 goto end; 534 goto end;
466 } 535 }
467 battery->info.capacity_mode = (battery_mode & 0x8000) >> 15; 536 battery->info.capacity_mode = (battery_mode & 0x8000) >> 15;
468 537
469 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10, 538 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x10,
470 &battery->info.full_charge_capacity, 539 &battery->info.full_charge_capacity);
471 &acpi_battery_smbus_err_handler);
472 if (result) { 540 if (result) {
473 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 541 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
474 "acpi_sbs_smbus_read_word() failed\n")); 542 "acpi_sbs_read_word() failed"));
475 goto end; 543 goto end;
476 } 544 }
477 545
478 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18, 546 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x18,
479 &battery->info.design_capacity, 547 &battery->info.design_capacity);
480 &acpi_battery_smbus_err_handler);
481 548
482 if (result) { 549 if (result) {
550 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
551 "acpi_sbs_read_word() failed"));
483 goto end; 552 goto end;
484 } 553 }
485 554
486 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19, 555 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x19,
487 &battery->info.design_voltage, 556 &battery->info.design_voltage);
488 &acpi_battery_smbus_err_handler);
489 if (result) { 557 if (result) {
490 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 558 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
491 "acpi_sbs_smbus_read_word() failed\n")); 559 "acpi_sbs_read_word() failed"));
492 goto end; 560 goto end;
493 } 561 }
494 562
495 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a, 563 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1a,
496 &specification_info, 564 &specification_info);
497 &acpi_battery_smbus_err_handler);
498 if (result) { 565 if (result) {
499 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 566 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
500 "acpi_sbs_smbus_read_word() failed\n")); 567 "acpi_sbs_read_word() failed"));
501 goto end; 568 goto end;
502 } 569 }
503 570
@@ -529,37 +596,35 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
529 battery->info.ipscale = 1; 596 battery->info.ipscale = 1;
530 } 597 }
531 598
532 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c, 599 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c,
533 &battery->info.serial_number, 600 &battery->info.serial_number);
534 &acpi_battery_smbus_err_handler);
535 if (result) { 601 if (result) {
602 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
603 "acpi_sbs_read_word() failed"));
536 goto end; 604 goto end;
537 } 605 }
538 606
539 result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20, 607 result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x20,
540 battery->info.manufacturer_name, 608 battery->info.manufacturer_name);
541 &acpi_battery_smbus_err_handler);
542 if (result) { 609 if (result) {
543 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 610 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
544 "acpi_sbs_smbus_read_str() failed\n")); 611 "acpi_sbs_read_str() failed"));
545 goto end; 612 goto end;
546 } 613 }
547 614
548 result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21, 615 result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x21,
549 battery->info.device_name, 616 battery->info.device_name);
550 &acpi_battery_smbus_err_handler);
551 if (result) { 617 if (result) {
552 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 618 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
553 "acpi_sbs_smbus_read_str() failed\n")); 619 "acpi_sbs_read_str() failed"));
554 goto end; 620 goto end;
555 } 621 }
556 622
557 result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22, 623 result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x22,
558 battery->info.device_chemistry, 624 battery->info.device_chemistry);
559 &acpi_battery_smbus_err_handler);
560 if (result) { 625 if (result) {
561 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 626 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
562 "acpi_sbs_smbus_read_str() failed\n")); 627 "acpi_sbs_read_str() failed"));
563 goto end; 628 goto end;
564 } 629 }
565 630
@@ -567,103 +632,60 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
567 return result; 632 return result;
568} 633}
569 634
570static void acpi_update_delay(struct acpi_sbs *sbs)
571{
572 if (sbs->zombie) {
573 return;
574 }
575 if (sbs->update_time2 > 0) {
576 msleep(sbs->update_time2 * 1000);
577 }
578}
579
580static int acpi_battery_get_state(struct acpi_battery *battery) 635static int acpi_battery_get_state(struct acpi_battery *battery)
581{ 636{
582 struct acpi_ec_smbus *smbus = battery->sbs->smbus; 637 struct acpi_sbs *sbs = battery->sbs;
583 int result = 0; 638 int result = 0;
584 639
585 acpi_update_delay(battery->sbs); 640 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09,
586 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09, 641 &battery->state.voltage);
587 &battery->state.voltage,
588 &acpi_battery_smbus_err_handler);
589 if (result) { 642 if (result) {
590 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 643 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
591 "acpi_sbs_smbus_read_word() failed\n")); 644 "acpi_sbs_read_word() failed"));
592 goto end; 645 goto end;
593 } 646 }
594 647
595 acpi_update_delay(battery->sbs); 648 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a,
596 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a, 649 &battery->state.amperage);
597 &battery->state.amperage,
598 &acpi_battery_smbus_err_handler);
599 if (result) { 650 if (result) {
600 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 651 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
601 "acpi_sbs_smbus_read_word() failed\n")); 652 "acpi_sbs_read_word() failed"));
602 goto end; 653 goto end;
603 } 654 }
604 655
605 acpi_update_delay(battery->sbs); 656 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f,
606 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f, 657 &battery->state.remaining_capacity);
607 &battery->state.remaining_capacity,
608 &acpi_battery_smbus_err_handler);
609 if (result) { 658 if (result) {
610 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 659 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
611 "acpi_sbs_smbus_read_word() failed\n")); 660 "acpi_sbs_read_word() failed"));
612 goto end; 661 goto end;
613 } 662 }
614 663
615 acpi_update_delay(battery->sbs); 664 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16,
616 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12, 665 &battery->state.battery_state);
617 &battery->state.average_time_to_empty,
618 &acpi_battery_smbus_err_handler);
619 if (result) { 666 if (result) {
620 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 667 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
621 "acpi_sbs_smbus_read_word() failed\n")); 668 "acpi_sbs_read_word() failed"));
622 goto end; 669 goto end;
623 } 670 }
624 671
625 acpi_update_delay(battery->sbs);
626 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13,
627 &battery->state.average_time_to_full,
628 &acpi_battery_smbus_err_handler);
629 if (result) {
630 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
631 "acpi_sbs_smbus_read_word() failed\n"));
632 goto end;
633 }
634
635 acpi_update_delay(battery->sbs);
636 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16,
637 &battery->state.battery_status,
638 &acpi_battery_smbus_err_handler);
639 if (result) {
640 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
641 "acpi_sbs_smbus_read_word() failed\n"));
642 goto end;
643 }
644
645 acpi_update_delay(battery->sbs);
646
647 end: 672 end:
648 return result; 673 return result;
649} 674}
650 675
651static int acpi_battery_get_alarm(struct acpi_battery *battery) 676static int acpi_battery_get_alarm(struct acpi_battery *battery)
652{ 677{
653 struct acpi_ec_smbus *smbus = battery->sbs->smbus; 678 struct acpi_sbs *sbs = battery->sbs;
654 int result = 0; 679 int result = 0;
655 680
656 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, 681 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
657 &battery->alarm.remaining_capacity, 682 &battery->alarm.remaining_capacity);
658 &acpi_battery_smbus_err_handler);
659 if (result) { 683 if (result) {
660 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 684 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
661 "acpi_sbs_smbus_read_word() failed\n")); 685 "acpi_sbs_read_word() failed"));
662 goto end; 686 goto end;
663 } 687 }
664 688
665 acpi_update_delay(battery->sbs);
666
667 end: 689 end:
668 690
669 return result; 691 return result;
@@ -672,15 +694,15 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery)
672static int acpi_battery_set_alarm(struct acpi_battery *battery, 694static int acpi_battery_set_alarm(struct acpi_battery *battery,
673 unsigned long alarm) 695 unsigned long alarm)
674{ 696{
675 struct acpi_ec_smbus *smbus = battery->sbs->smbus; 697 struct acpi_sbs *sbs = battery->sbs;
676 int result = 0; 698 int result = 0;
677 s16 battery_mode; 699 s16 battery_mode;
678 int foo; 700 int foo;
679 701
680 result = acpi_battery_select(battery); 702 result = acpi_battery_select(battery);
681 if (result) { 703 if (result) {
682 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 704 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
683 "acpi_battery_select() failed\n")); 705 "acpi_battery_select() failed"));
684 goto end; 706 goto end;
685 } 707 }
686 708
@@ -688,33 +710,29 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
688 710
689 if (alarm > 0) { 711 if (alarm > 0) {
690 result = 712 result =
691 acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03, 713 acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03,
692 &battery_mode, 714 &battery_mode);
693 &acpi_battery_smbus_err_handler);
694 if (result) { 715 if (result) {
695 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 716 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
696 "acpi_sbs_smbus_read_word() failed\n")); 717 "acpi_sbs_read_word() failed"));
697 goto end; 718 goto end;
698 } 719 }
699 720
700 result = 721 result =
701 acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, 722 acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
702 battery_mode & 0xbfff, 723 battery_mode & 0xbfff);
703 &acpi_battery_smbus_err_handler);
704 if (result) { 724 if (result) {
705 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 725 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
706 "acpi_sbs_smbus_write_word() failed\n")); 726 "acpi_sbs_write_word() failed"));
707 goto end; 727 goto end;
708 } 728 }
709 } 729 }
710 730
711 foo = alarm / (battery->info.capacity_mode ? 10 : 1); 731 foo = alarm / (battery->info.capacity_mode ? 10 : 1);
712 result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, 732 result = acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, foo);
713 foo,
714 &acpi_battery_smbus_err_handler);
715 if (result) { 733 if (result) {
716 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 734 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
717 "acpi_sbs_smbus_write_word() failed\n")); 735 "acpi_sbs_write_word() failed"));
718 goto end; 736 goto end;
719 } 737 }
720 738
@@ -725,6 +743,7 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
725 743
726static int acpi_battery_set_mode(struct acpi_battery *battery) 744static int acpi_battery_set_mode(struct acpi_battery *battery)
727{ 745{
746 struct acpi_sbs *sbs = battery->sbs;
728 int result = 0; 747 int result = 0;
729 s16 battery_mode; 748 s16 battery_mode;
730 749
@@ -732,12 +751,11 @@ static int acpi_battery_set_mode(struct acpi_battery *battery)
732 goto end; 751 goto end;
733 } 752 }
734 753
735 result = acpi_sbs_smbus_read_word(battery->sbs->smbus, 754 result = acpi_sbs_read_word(sbs,
736 ACPI_SB_SMBUS_ADDR, 0x03, 755 ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
737 &battery_mode, NULL);
738 if (result) { 756 if (result) {
739 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 757 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
740 "acpi_sbs_smbus_read_word() failed\n")); 758 "acpi_sbs_read_word() failed"));
741 goto end; 759 goto end;
742 } 760 }
743 761
@@ -746,21 +764,19 @@ static int acpi_battery_set_mode(struct acpi_battery *battery)
746 } else { 764 } else {
747 battery_mode |= 0x8000; 765 battery_mode |= 0x8000;
748 } 766 }
749 result = acpi_sbs_smbus_write_word(battery->sbs->smbus, 767 result = acpi_sbs_write_word(sbs,
750 ACPI_SB_SMBUS_ADDR, 0x03, 768 ACPI_SB_SMBUS_ADDR, 0x03, battery_mode);
751 battery_mode, NULL);
752 if (result) { 769 if (result) {
753 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 770 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
754 "acpi_sbs_smbus_write_word() failed\n")); 771 "acpi_sbs_write_word() failed"));
755 goto end; 772 goto end;
756 } 773 }
757 774
758 result = acpi_sbs_smbus_read_word(battery->sbs->smbus, 775 result = acpi_sbs_read_word(sbs,
759 ACPI_SB_SMBUS_ADDR, 0x03, 776 ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
760 &battery_mode, NULL);
761 if (result) { 777 if (result) {
762 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 778 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
763 "acpi_sbs_smbus_read_word() failed\n")); 779 "acpi_sbs_read_word() failed"));
764 goto end; 780 goto end;
765 } 781 }
766 782
@@ -774,36 +790,36 @@ static int acpi_battery_init(struct acpi_battery *battery)
774 790
775 result = acpi_battery_select(battery); 791 result = acpi_battery_select(battery);
776 if (result) { 792 if (result) {
777 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 793 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
778 "acpi_battery_init() failed\n")); 794 "acpi_battery_select() failed"));
779 goto end; 795 goto end;
780 } 796 }
781 797
782 result = acpi_battery_set_mode(battery); 798 result = acpi_battery_set_mode(battery);
783 if (result) { 799 if (result) {
784 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 800 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
785 "acpi_battery_set_mode() failed\n")); 801 "acpi_battery_set_mode() failed"));
786 goto end; 802 goto end;
787 } 803 }
788 804
789 result = acpi_battery_get_info(battery); 805 result = acpi_battery_get_info(battery);
790 if (result) { 806 if (result) {
791 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 807 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
792 "acpi_battery_get_info() failed\n")); 808 "acpi_battery_get_info() failed"));
793 goto end; 809 goto end;
794 } 810 }
795 811
796 result = acpi_battery_get_state(battery); 812 result = acpi_battery_get_state(battery);
797 if (result) { 813 if (result) {
798 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 814 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
799 "acpi_battery_get_state() failed\n")); 815 "acpi_battery_get_state() failed"));
800 goto end; 816 goto end;
801 } 817 }
802 818
803 result = acpi_battery_get_alarm(battery); 819 result = acpi_battery_get_alarm(battery);
804 if (result) { 820 if (result) {
805 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 821 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
806 "acpi_battery_get_alarm() failed\n")); 822 "acpi_battery_get_alarm() failed"));
807 goto end; 823 goto end;
808 } 824 }
809 825
@@ -813,20 +829,19 @@ static int acpi_battery_init(struct acpi_battery *battery)
813 829
814static int acpi_ac_get_present(struct acpi_sbs *sbs) 830static int acpi_ac_get_present(struct acpi_sbs *sbs)
815{ 831{
816 struct acpi_ec_smbus *smbus = sbs->smbus;
817 int result = 0; 832 int result = 0;
818 s16 charger_status; 833 s16 charger_status;
819 834
820 result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13, 835 result = acpi_sbs_read_word(sbs, ACPI_SBC_SMBUS_ADDR, 0x13,
821 &charger_status, NULL); 836 &charger_status);
822 837
823 if (result) { 838 if (result) {
824 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 839 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
825 "acpi_sbs_smbus_read_word() failed\n")); 840 "acpi_sbs_read_word() failed"));
826 goto end; 841 goto end;
827 } 842 }
828 843
829 sbs->ac_present = (charger_status & 0x8000) >> 15; 844 sbs->ac.ac_present = (charger_status & 0x8000) >> 15;
830 845
831 end: 846 end:
832 847
@@ -852,8 +867,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
852 if (!*dir) { 867 if (!*dir) {
853 *dir = proc_mkdir(dir_name, parent_dir); 868 *dir = proc_mkdir(dir_name, parent_dir);
854 if (!*dir) { 869 if (!*dir) {
855 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 870 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
856 "proc_mkdir() failed\n")); 871 "proc_mkdir() failed"));
857 return -ENODEV; 872 return -ENODEV;
858 } 873 }
859 (*dir)->owner = THIS_MODULE; 874 (*dir)->owner = THIS_MODULE;
@@ -863,8 +878,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
863 if (info_fops) { 878 if (info_fops) {
864 entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir); 879 entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
865 if (!entry) { 880 if (!entry) {
866 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 881 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
867 "create_proc_entry() failed\n")); 882 "create_proc_entry() failed"));
868 } else { 883 } else {
869 entry->proc_fops = info_fops; 884 entry->proc_fops = info_fops;
870 entry->data = data; 885 entry->data = data;
@@ -876,8 +891,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
876 if (state_fops) { 891 if (state_fops) {
877 entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir); 892 entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
878 if (!entry) { 893 if (!entry) {
879 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 894 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
880 "create_proc_entry() failed\n")); 895 "create_proc_entry() failed"));
881 } else { 896 } else {
882 entry->proc_fops = state_fops; 897 entry->proc_fops = state_fops;
883 entry->data = data; 898 entry->data = data;
@@ -889,8 +904,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
889 if (alarm_fops) { 904 if (alarm_fops) {
890 entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir); 905 entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
891 if (!entry) { 906 if (!entry) {
892 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 907 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
893 "create_proc_entry() failed\n")); 908 "create_proc_entry() failed"));
894 } else { 909 } else {
895 entry->proc_fops = alarm_fops; 910 entry->proc_fops = alarm_fops;
896 entry->data = data; 911 entry->data = data;
@@ -923,24 +938,27 @@ static struct proc_dir_entry *acpi_battery_dir = NULL;
923static int acpi_battery_read_info(struct seq_file *seq, void *offset) 938static int acpi_battery_read_info(struct seq_file *seq, void *offset)
924{ 939{
925 struct acpi_battery *battery = seq->private; 940 struct acpi_battery *battery = seq->private;
941 struct acpi_sbs *sbs = battery->sbs;
926 int cscale; 942 int cscale;
927 int result = 0; 943 int result = 0;
928 944
929 if (battery->sbs->zombie) { 945 if (sbs_mutex_lock(sbs)) {
930 return -ENODEV; 946 return -ENODEV;
931 } 947 }
932 948
933 down(&sbs_sem); 949 result = acpi_check_update_proc(sbs);
950 if (result)
951 goto end;
934 952
935 if (update_mode == REQUEST_UPDATE_MODE) { 953 if (update_time == 0) {
936 result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_INFO); 954 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO);
937 if (result) { 955 if (result) {
938 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 956 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
939 "acpi_sbs_update_run() failed\n")); 957 "acpi_sbs_update_run() failed"));
940 } 958 }
941 } 959 }
942 960
943 if (acpi_battery_is_present(battery)) { 961 if (battery->battery_present) {
944 seq_printf(seq, "present: yes\n"); 962 seq_printf(seq, "present: yes\n");
945 } else { 963 } else {
946 seq_printf(seq, "present: no\n"); 964 seq_printf(seq, "present: no\n");
@@ -952,13 +970,13 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
952 } else { 970 } else {
953 cscale = battery->info.ipscale; 971 cscale = battery->info.ipscale;
954 } 972 }
955 seq_printf(seq, "design capacity: %i%s", 973 seq_printf(seq, "design capacity: %i%s\n",
956 battery->info.design_capacity * cscale, 974 battery->info.design_capacity * cscale,
957 battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); 975 battery->info.capacity_mode ? "0 mWh" : " mAh");
958 976
959 seq_printf(seq, "last full capacity: %i%s", 977 seq_printf(seq, "last full capacity: %i%s\n",
960 battery->info.full_charge_capacity * cscale, 978 battery->info.full_charge_capacity * cscale,
961 battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); 979 battery->info.capacity_mode ? "0 mWh" : " mAh");
962 980
963 seq_printf(seq, "battery technology: rechargeable\n"); 981 seq_printf(seq, "battery technology: rechargeable\n");
964 982
@@ -984,7 +1002,7 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
984 1002
985 end: 1003 end:
986 1004
987 up(&sbs_sem); 1005 sbs_mutex_unlock(sbs);
988 1006
989 return result; 1007 return result;
990} 1008}
@@ -996,26 +1014,29 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
996 1014
997static int acpi_battery_read_state(struct seq_file *seq, void *offset) 1015static int acpi_battery_read_state(struct seq_file *seq, void *offset)
998{ 1016{
999 struct acpi_battery *battery = (struct acpi_battery *)seq->private; 1017 struct acpi_battery *battery = seq->private;
1018 struct acpi_sbs *sbs = battery->sbs;
1000 int result = 0; 1019 int result = 0;
1001 int cscale; 1020 int cscale;
1002 int foo; 1021 int foo;
1003 1022
1004 if (battery->sbs->zombie) { 1023 if (sbs_mutex_lock(sbs)) {
1005 return -ENODEV; 1024 return -ENODEV;
1006 } 1025 }
1007 1026
1008 down(&sbs_sem); 1027 result = acpi_check_update_proc(sbs);
1028 if (result)
1029 goto end;
1009 1030
1010 if (update_mode == REQUEST_UPDATE_MODE) { 1031 if (update_time == 0) {
1011 result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_STATE); 1032 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_STATE);
1012 if (result) { 1033 if (result) {
1013 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1034 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1014 "acpi_sbs_update_run() failed\n")); 1035 "acpi_sbs_update_run() failed"));
1015 } 1036 }
1016 } 1037 }
1017 1038
1018 if (acpi_battery_is_present(battery)) { 1039 if (battery->battery_present) {
1019 seq_printf(seq, "present: yes\n"); 1040 seq_printf(seq, "present: yes\n");
1020 } else { 1041 } else {
1021 seq_printf(seq, "present: no\n"); 1042 seq_printf(seq, "present: no\n");
@@ -1028,7 +1049,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
1028 cscale = battery->info.ipscale; 1049 cscale = battery->info.ipscale;
1029 } 1050 }
1030 1051
1031 if (battery->state.battery_status & 0x0010) { 1052 if (battery->state.battery_state & 0x0010) {
1032 seq_printf(seq, "capacity state: critical\n"); 1053 seq_printf(seq, "capacity state: critical\n");
1033 } else { 1054 } else {
1034 seq_printf(seq, "capacity state: ok\n"); 1055 seq_printf(seq, "capacity state: ok\n");
@@ -1052,16 +1073,16 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
1052 battery->info.capacity_mode ? "mW" : "mA"); 1073 battery->info.capacity_mode ? "mW" : "mA");
1053 } 1074 }
1054 1075
1055 seq_printf(seq, "remaining capacity: %i%s", 1076 seq_printf(seq, "remaining capacity: %i%s\n",
1056 battery->state.remaining_capacity * cscale, 1077 battery->state.remaining_capacity * cscale,
1057 battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); 1078 battery->info.capacity_mode ? "0 mWh" : " mAh");
1058 1079
1059 seq_printf(seq, "present voltage: %i mV\n", 1080 seq_printf(seq, "present voltage: %i mV\n",
1060 battery->state.voltage * battery->info.vscale); 1081 battery->state.voltage * battery->info.vscale);
1061 1082
1062 end: 1083 end:
1063 1084
1064 up(&sbs_sem); 1085 sbs_mutex_unlock(sbs);
1065 1086
1066 return result; 1087 return result;
1067} 1088}
@@ -1074,24 +1095,27 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
1074static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) 1095static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
1075{ 1096{
1076 struct acpi_battery *battery = seq->private; 1097 struct acpi_battery *battery = seq->private;
1098 struct acpi_sbs *sbs = battery->sbs;
1077 int result = 0; 1099 int result = 0;
1078 int cscale; 1100 int cscale;
1079 1101
1080 if (battery->sbs->zombie) { 1102 if (sbs_mutex_lock(sbs)) {
1081 return -ENODEV; 1103 return -ENODEV;
1082 } 1104 }
1083 1105
1084 down(&sbs_sem); 1106 result = acpi_check_update_proc(sbs);
1107 if (result)
1108 goto end;
1085 1109
1086 if (update_mode == REQUEST_UPDATE_MODE) { 1110 if (update_time == 0) {
1087 result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_ALARM); 1111 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_ALARM);
1088 if (result) { 1112 if (result) {
1089 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1113 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1090 "acpi_sbs_update_run() failed\n")); 1114 "acpi_sbs_update_run() failed"));
1091 } 1115 }
1092 } 1116 }
1093 1117
1094 if (!acpi_battery_is_present(battery)) { 1118 if (!battery->battery_present) {
1095 seq_printf(seq, "present: no\n"); 1119 seq_printf(seq, "present: no\n");
1096 goto end; 1120 goto end;
1097 } 1121 }
@@ -1104,16 +1128,16 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
1104 1128
1105 seq_printf(seq, "alarm: "); 1129 seq_printf(seq, "alarm: ");
1106 if (battery->alarm.remaining_capacity) { 1130 if (battery->alarm.remaining_capacity) {
1107 seq_printf(seq, "%i%s", 1131 seq_printf(seq, "%i%s\n",
1108 battery->alarm.remaining_capacity * cscale, 1132 battery->alarm.remaining_capacity * cscale,
1109 battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); 1133 battery->info.capacity_mode ? "0 mWh" : " mAh");
1110 } else { 1134 } else {
1111 seq_printf(seq, "disabled\n"); 1135 seq_printf(seq, "disabled\n");
1112 } 1136 }
1113 1137
1114 end: 1138 end:
1115 1139
1116 up(&sbs_sem); 1140 sbs_mutex_unlock(sbs);
1117 1141
1118 return result; 1142 return result;
1119} 1143}
@@ -1124,16 +1148,19 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
1124{ 1148{
1125 struct seq_file *seq = file->private_data; 1149 struct seq_file *seq = file->private_data;
1126 struct acpi_battery *battery = seq->private; 1150 struct acpi_battery *battery = seq->private;
1151 struct acpi_sbs *sbs = battery->sbs;
1127 char alarm_string[12] = { '\0' }; 1152 char alarm_string[12] = { '\0' };
1128 int result, old_alarm, new_alarm; 1153 int result, old_alarm, new_alarm;
1129 1154
1130 if (battery->sbs->zombie) { 1155 if (sbs_mutex_lock(sbs)) {
1131 return -ENODEV; 1156 return -ENODEV;
1132 } 1157 }
1133 1158
1134 down(&sbs_sem); 1159 result = acpi_check_update_proc(sbs);
1160 if (result)
1161 goto end;
1135 1162
1136 if (!acpi_battery_is_present(battery)) { 1163 if (!battery->battery_present) {
1137 result = -ENODEV; 1164 result = -ENODEV;
1138 goto end; 1165 goto end;
1139 } 1166 }
@@ -1155,21 +1182,21 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
1155 1182
1156 result = acpi_battery_set_alarm(battery, new_alarm); 1183 result = acpi_battery_set_alarm(battery, new_alarm);
1157 if (result) { 1184 if (result) {
1158 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1185 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1159 "acpi_battery_set_alarm() failed\n")); 1186 "acpi_battery_set_alarm() failed"));
1160 acpi_battery_set_alarm(battery, old_alarm); 1187 acpi_battery_set_alarm(battery, old_alarm);
1161 goto end; 1188 goto end;
1162 } 1189 }
1163 result = acpi_battery_get_alarm(battery); 1190 result = acpi_battery_get_alarm(battery);
1164 if (result) { 1191 if (result) {
1165 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1192 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1166 "acpi_battery_get_alarm() failed\n")); 1193 "acpi_battery_get_alarm() failed"));
1167 acpi_battery_set_alarm(battery, old_alarm); 1194 acpi_battery_set_alarm(battery, old_alarm);
1168 goto end; 1195 goto end;
1169 } 1196 }
1170 1197
1171 end: 1198 end:
1172 up(&sbs_sem); 1199 sbs_mutex_unlock(sbs);
1173 1200
1174 if (result) { 1201 if (result) {
1175 return result; 1202 return result;
@@ -1217,24 +1244,22 @@ static int acpi_ac_read_state(struct seq_file *seq, void *offset)
1217 struct acpi_sbs *sbs = seq->private; 1244 struct acpi_sbs *sbs = seq->private;
1218 int result; 1245 int result;
1219 1246
1220 if (sbs->zombie) { 1247 if (sbs_mutex_lock(sbs)) {
1221 return -ENODEV; 1248 return -ENODEV;
1222 } 1249 }
1223 1250
1224 down(&sbs_sem); 1251 if (update_time == 0) {
1225 1252 result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_AC_STATE);
1226 if (update_mode == REQUEST_UPDATE_MODE) {
1227 result = acpi_sbs_update_run(sbs, DATA_TYPE_AC_STATE);
1228 if (result) { 1253 if (result) {
1229 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1254 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1230 "acpi_sbs_update_run() failed\n")); 1255 "acpi_sbs_update_run() failed"));
1231 } 1256 }
1232 } 1257 }
1233 1258
1234 seq_printf(seq, "state: %s\n", 1259 seq_printf(seq, "state: %s\n",
1235 sbs->ac_present ? "on-line" : "off-line"); 1260 sbs->ac.ac_present ? "on-line" : "off-line");
1236 1261
1237 up(&sbs_sem); 1262 sbs_mutex_unlock(sbs);
1238 1263
1239 return 0; 1264 return 0;
1240} 1265}
@@ -1275,25 +1300,25 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
1275 1300
1276 result = acpi_battery_select(battery); 1301 result = acpi_battery_select(battery);
1277 if (result) { 1302 if (result) {
1278 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1303 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1279 "acpi_battery_select() failed\n")); 1304 "acpi_battery_select() failed"));
1280 goto end; 1305 goto end;
1281 } 1306 }
1282 1307
1283 result = acpi_battery_get_present(battery); 1308 result = acpi_battery_get_present(battery);
1284 if (result) { 1309 if (result) {
1285 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1310 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1286 "acpi_battery_get_present() failed\n")); 1311 "acpi_battery_get_present() failed"));
1287 goto end; 1312 goto end;
1288 } 1313 }
1289 1314
1290 is_present = acpi_battery_is_present(battery); 1315 is_present = battery->battery_present;
1291 1316
1292 if (is_present) { 1317 if (is_present) {
1293 result = acpi_battery_init(battery); 1318 result = acpi_battery_init(battery);
1294 if (result) { 1319 if (result) {
1295 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1320 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1296 "acpi_battery_init() failed\n")); 1321 "acpi_battery_init() failed"));
1297 goto end; 1322 goto end;
1298 } 1323 }
1299 battery->init_state = 1; 1324 battery->init_state = 1;
@@ -1308,12 +1333,16 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
1308 &acpi_battery_state_fops, 1333 &acpi_battery_state_fops,
1309 &acpi_battery_alarm_fops, battery); 1334 &acpi_battery_alarm_fops, battery);
1310 if (result) { 1335 if (result) {
1311 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1336 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1312 "acpi_sbs_generic_add_fs() failed\n")); 1337 "acpi_sbs_generic_add_fs() failed"));
1313 goto end; 1338 goto end;
1314 } 1339 }
1315 battery->alive = 1; 1340 battery->alive = 1;
1316 1341
1342 printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
1343 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name,
1344 sbs->battery->battery_present ? "present" : "absent");
1345
1317 end: 1346 end:
1318 return result; 1347 return result;
1319} 1348}
@@ -1333,8 +1362,8 @@ static int acpi_ac_add(struct acpi_sbs *sbs)
1333 1362
1334 result = acpi_ac_get_present(sbs); 1363 result = acpi_ac_get_present(sbs);
1335 if (result) { 1364 if (result) {
1336 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1365 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1337 "acpi_ac_get_present() failed\n")); 1366 "acpi_ac_get_present() failed"));
1338 goto end; 1367 goto end;
1339 } 1368 }
1340 1369
@@ -1343,11 +1372,15 @@ static int acpi_ac_add(struct acpi_sbs *sbs)
1343 ACPI_AC_DIR_NAME, 1372 ACPI_AC_DIR_NAME,
1344 NULL, &acpi_ac_state_fops, NULL, sbs); 1373 NULL, &acpi_ac_state_fops, NULL, sbs);
1345 if (result) { 1374 if (result) {
1346 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1375 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1347 "acpi_sbs_generic_add_fs() failed\n")); 1376 "acpi_sbs_generic_add_fs() failed"));
1348 goto end; 1377 goto end;
1349 } 1378 }
1350 1379
1380 printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
1381 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
1382 ACPI_AC_DIR_NAME, sbs->ac.ac_present ? "on-line" : "off-line");
1383
1351 end: 1384 end:
1352 1385
1353 return result; 1386 return result;
@@ -1361,45 +1394,85 @@ static void acpi_ac_remove(struct acpi_sbs *sbs)
1361 } 1394 }
1362} 1395}
1363 1396
1364static void acpi_sbs_update_queue_run(unsigned long data) 1397static void acpi_sbs_update_time_run(unsigned long data)
1365{ 1398{
1366 acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_queue, (void *)data); 1399 acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_time, (void *)data);
1367} 1400}
1368 1401
1369static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type) 1402static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type)
1370{ 1403{
1371 struct acpi_battery *battery; 1404 struct acpi_battery *battery;
1372 int result = 0; 1405 int result = 0, cnt;
1373 int old_ac_present; 1406 int old_ac_present = -1;
1374 int old_battery_present; 1407 int old_battery_present = -1;
1375 int new_ac_present; 1408 int new_ac_present = -1;
1376 int new_battery_present; 1409 int new_battery_present = -1;
1377 int id; 1410 int id_min = 0, id_max = MAX_SBS_BAT - 1;
1378 char dir_name[32]; 1411 char dir_name[32];
1379 int do_battery_init, do_ac_init; 1412 int do_battery_init = 0, do_ac_init = 0;
1380 s16 old_remaining_capacity; 1413 int old_remaining_capacity = 0;
1414 int update_ac = 1, update_battery = 1;
1415 int up_tm = update_time;
1381 1416
1382 if (sbs->zombie) { 1417 if (sbs_zombie(sbs)) {
1383 goto end; 1418 goto end;
1384 } 1419 }
1385 1420
1386 old_ac_present = acpi_ac_is_present(sbs); 1421 if (id >= 0) {
1422 id_min = id_max = id;
1423 }
1424
1425 if (data_type == DATA_TYPE_COMMON && up_tm > 0) {
1426 cnt = up_tm / (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
1427 if (sbs->run_cnt % cnt != 0) {
1428 update_battery = 0;
1429 }
1430 }
1431
1432 sbs->run_cnt++;
1433
1434 if (!update_ac && !update_battery) {
1435 goto end;
1436 }
1437
1438 old_ac_present = sbs->ac.ac_present;
1387 1439
1388 result = acpi_ac_get_present(sbs); 1440 result = acpi_ac_get_present(sbs);
1389 if (result) { 1441 if (result) {
1390 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1442 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1391 "acpi_ac_get_present() failed\n")); 1443 "acpi_ac_get_present() failed"));
1392 } 1444 }
1393 1445
1394 new_ac_present = acpi_ac_is_present(sbs); 1446 new_ac_present = sbs->ac.ac_present;
1395 1447
1396 do_ac_init = (old_ac_present != new_ac_present); 1448 do_ac_init = (old_ac_present != new_ac_present);
1449 if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) {
1450 do_ac_init = 1;
1451 }
1397 1452
1398 if (data_type == DATA_TYPE_AC_STATE) { 1453 if (do_ac_init) {
1454 result = acpi_sbs_generate_event(sbs->device,
1455 ACPI_SBS_AC_NOTIFY_STATUS,
1456 new_ac_present,
1457 ACPI_AC_DIR_NAME,
1458 ACPI_AC_CLASS);
1459 if (result) {
1460 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1461 "acpi_sbs_generate_event() failed"));
1462 }
1463 }
1464
1465 if (data_type == DATA_TYPE_COMMON) {
1466 if (!do_ac_init && !update_battery) {
1467 goto end;
1468 }
1469 }
1470
1471 if (data_type == DATA_TYPE_AC_STATE && !do_ac_init) {
1399 goto end; 1472 goto end;
1400 } 1473 }
1401 1474
1402 for (id = 0; id < MAX_SBS_BAT; id++) { 1475 for (id = id_min; id <= id_max; id++) {
1403 battery = &sbs->battery[id]; 1476 battery = &sbs->battery[id];
1404 if (battery->alive == 0) { 1477 if (battery->alive == 0) {
1405 continue; 1478 continue;
@@ -1407,94 +1480,92 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
1407 1480
1408 old_remaining_capacity = battery->state.remaining_capacity; 1481 old_remaining_capacity = battery->state.remaining_capacity;
1409 1482
1410 old_battery_present = acpi_battery_is_present(battery); 1483 old_battery_present = battery->battery_present;
1411 1484
1412 result = acpi_battery_select(battery); 1485 result = acpi_battery_select(battery);
1413 if (result) { 1486 if (result) {
1414 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1487 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1415 "acpi_battery_select() failed\n")); 1488 "acpi_battery_select() failed"));
1416 }
1417 if (sbs->zombie) {
1418 goto end;
1419 } 1489 }
1420 1490
1421 result = acpi_battery_get_present(battery); 1491 result = acpi_battery_get_present(battery);
1422 if (result) { 1492 if (result) {
1423 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1493 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1424 "acpi_battery_get_present() failed\n")); 1494 "acpi_battery_get_present() failed"));
1425 }
1426 if (sbs->zombie) {
1427 goto end;
1428 } 1495 }
1429 1496
1430 new_battery_present = acpi_battery_is_present(battery); 1497 new_battery_present = battery->battery_present;
1431 1498
1432 do_battery_init = ((old_battery_present != new_battery_present) 1499 do_battery_init = ((old_battery_present != new_battery_present)
1433 && new_battery_present); 1500 && new_battery_present);
1434 1501 if (!new_battery_present)
1435 if (sbs->zombie) { 1502 goto event;
1503 if (do_ac_init || do_battery_init) {
1504 result = acpi_battery_init(battery);
1505 if (result) {
1506 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1507 "acpi_battery_init() "
1508 "failed"));
1509 }
1510 }
1511 if (sbs_zombie(sbs)) {
1436 goto end; 1512 goto end;
1437 } 1513 }
1438 if (do_ac_init || do_battery_init || 1514
1439 update_info_mode || sbs->update_info_mode) { 1515 if ((data_type == DATA_TYPE_COMMON
1440 if (sbs->update_info_mode) { 1516 || data_type == DATA_TYPE_INFO)
1441 sbs->update_info_mode = 0; 1517 && new_battery_present) {
1442 } else { 1518 result = acpi_battery_get_info(battery);
1443 sbs->update_info_mode = 1;
1444 }
1445 result = acpi_battery_init(battery);
1446 if (result) { 1519 if (result) {
1447 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1520 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1448 "acpi_battery_init() " 1521 "acpi_battery_get_info() failed"));
1449 "failed\n"));
1450 } 1522 }
1451 } 1523 }
1452 if (data_type == DATA_TYPE_INFO) { 1524 if (data_type == DATA_TYPE_INFO) {
1453 continue; 1525 continue;
1454 } 1526 }
1455 1527 if (sbs_zombie(sbs)) {
1456 if (sbs->zombie) {
1457 goto end; 1528 goto end;
1458 } 1529 }
1459 if (new_battery_present) {
1460 result = acpi_battery_get_alarm(battery);
1461 if (result) {
1462 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1463 "acpi_battery_get_alarm() "
1464 "failed\n"));
1465 }
1466 if (data_type == DATA_TYPE_ALARM) {
1467 continue;
1468 }
1469 1530
1531 if ((data_type == DATA_TYPE_COMMON
1532 || data_type == DATA_TYPE_STATE)
1533 && new_battery_present) {
1470 result = acpi_battery_get_state(battery); 1534 result = acpi_battery_get_state(battery);
1471 if (result) { 1535 if (result) {
1472 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1536 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1473 "acpi_battery_get_state() " 1537 "acpi_battery_get_state() failed"));
1474 "failed\n"));
1475 } 1538 }
1476 } 1539 }
1477 if (sbs->zombie) { 1540 if (data_type == DATA_TYPE_STATE) {
1478 goto end; 1541 goto event;
1479 } 1542 }
1480 if (data_type != DATA_TYPE_COMMON) { 1543 if (sbs_zombie(sbs)) {
1481 continue; 1544 goto end;
1482 } 1545 }
1483 1546
1484 if (old_battery_present != new_battery_present) { 1547 if ((data_type == DATA_TYPE_COMMON
1485 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); 1548 || data_type == DATA_TYPE_ALARM)
1486 result = acpi_sbs_generate_event(sbs->device, 1549 && new_battery_present) {
1487 ACPI_SBS_BATTERY_NOTIFY_STATUS, 1550 result = acpi_battery_get_alarm(battery);
1488 new_battery_present,
1489 dir_name,
1490 ACPI_BATTERY_CLASS);
1491 if (result) { 1551 if (result) {
1492 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1552 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1493 "acpi_sbs_generate_event() " 1553 "acpi_battery_get_alarm() "
1494 "failed\n")); 1554 "failed"));
1495 } 1555 }
1496 } 1556 }
1497 if (old_remaining_capacity != battery->state.remaining_capacity) { 1557 if (data_type == DATA_TYPE_ALARM) {
1558 continue;
1559 }
1560 if (sbs_zombie(sbs)) {
1561 goto end;
1562 }
1563
1564 event:
1565
1566 if (old_battery_present != new_battery_present || do_ac_init ||
1567 old_remaining_capacity !=
1568 battery->state.remaining_capacity) {
1498 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); 1569 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
1499 result = acpi_sbs_generate_event(sbs->device, 1570 result = acpi_sbs_generate_event(sbs->device,
1500 ACPI_SBS_BATTERY_NOTIFY_STATUS, 1571 ACPI_SBS_BATTERY_NOTIFY_STATUS,
@@ -1502,138 +1573,120 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
1502 dir_name, 1573 dir_name,
1503 ACPI_BATTERY_CLASS); 1574 ACPI_BATTERY_CLASS);
1504 if (result) { 1575 if (result) {
1505 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1576 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1506 "acpi_sbs_generate_event() failed\n")); 1577 "acpi_sbs_generate_event() "
1578 "failed"));
1507 } 1579 }
1508 } 1580 }
1509
1510 }
1511 if (sbs->zombie) {
1512 goto end;
1513 }
1514 if (data_type != DATA_TYPE_COMMON) {
1515 goto end;
1516 }
1517
1518 if (old_ac_present != new_ac_present) {
1519 result = acpi_sbs_generate_event(sbs->device,
1520 ACPI_SBS_AC_NOTIFY_STATUS,
1521 new_ac_present,
1522 ACPI_AC_DIR_NAME,
1523 ACPI_AC_CLASS);
1524 if (result) {
1525 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1526 "acpi_sbs_generate_event() failed\n"));
1527 }
1528 } 1581 }
1529 1582
1530 end: 1583 end:
1584
1531 return result; 1585 return result;
1532} 1586}
1533 1587
1534static void acpi_sbs_update_queue(void *data) 1588static void acpi_sbs_update_time(void *data)
1535{ 1589{
1536 struct acpi_sbs *sbs = data; 1590 struct acpi_sbs *sbs = data;
1537 unsigned long delay = -1; 1591 unsigned long delay = -1;
1538 int result; 1592 int result;
1593 unsigned int up_tm = update_time;
1539 1594
1540 if (sbs->zombie) { 1595 if (sbs_mutex_lock(sbs))
1541 goto end; 1596 return;
1542 }
1543 1597
1544 result = acpi_sbs_update_run(sbs, DATA_TYPE_COMMON); 1598 result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_COMMON);
1545 if (result) { 1599 if (result) {
1546 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1600 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1547 "acpi_sbs_update_run() failed\n")); 1601 "acpi_sbs_update_run() failed"));
1548 } 1602 }
1549 1603
1550 if (sbs->zombie) { 1604 if (sbs_zombie(sbs)) {
1551 goto end; 1605 goto end;
1552 } 1606 }
1553 1607
1554 if (update_mode == REQUEST_UPDATE_MODE) { 1608 if (!up_tm) {
1555 goto end; 1609 if (timer_pending(&sbs->update_timer))
1610 del_timer(&sbs->update_timer);
1611 } else {
1612 delay = (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
1613 delay = jiffies + HZ * delay;
1614 if (timer_pending(&sbs->update_timer)) {
1615 mod_timer(&sbs->update_timer, delay);
1616 } else {
1617 sbs->update_timer.data = (unsigned long)data;
1618 sbs->update_timer.function = acpi_sbs_update_time_run;
1619 sbs->update_timer.expires = delay;
1620 add_timer(&sbs->update_timer);
1621 }
1556 } 1622 }
1557 1623
1558 delay = jiffies + HZ * update_time;
1559 sbs->update_timer.data = (unsigned long)data;
1560 sbs->update_timer.function = acpi_sbs_update_queue_run;
1561 sbs->update_timer.expires = delay;
1562 add_timer(&sbs->update_timer);
1563 end: 1624 end:
1564 ; 1625
1626 sbs_mutex_unlock(sbs);
1565} 1627}
1566 1628
1567static int acpi_sbs_add(struct acpi_device *device) 1629static int acpi_sbs_add(struct acpi_device *device)
1568{ 1630{
1569 struct acpi_sbs *sbs = NULL; 1631 struct acpi_sbs *sbs = NULL;
1570 struct acpi_ec_hc *ec_hc = NULL; 1632 int result = 0, remove_result = 0;
1571 int result, remove_result = 0;
1572 unsigned long sbs_obj; 1633 unsigned long sbs_obj;
1573 int id, cnt; 1634 int id;
1574 acpi_status status = AE_OK; 1635 acpi_status status = AE_OK;
1636 unsigned long val;
1637
1638 status =
1639 acpi_evaluate_integer(device->parent->handle, "_EC", NULL, &val);
1640 if (ACPI_FAILURE(status)) {
1641 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC"));
1642 return -EIO;
1643 }
1575 1644
1576 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); 1645 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
1577 if (!sbs) { 1646 if (!sbs) {
1578 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n")); 1647 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kzalloc() failed"));
1579 return -ENOMEM; 1648 result = -ENOMEM;
1649 goto end;
1580 } 1650 }
1581 1651
1582 cnt = 0; 1652 mutex_init(&sbs->mutex);
1583 while (cnt < 10) {
1584 cnt++;
1585 ec_hc = acpi_get_ec_hc(device);
1586 if (ec_hc) {
1587 break;
1588 }
1589 msleep(1000);
1590 }
1591 1653
1592 if (!ec_hc) { 1654 sbs_mutex_lock(sbs);
1593 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1594 "acpi_get_ec_hc() failed: "
1595 "NO driver found for EC HC SMBus\n"));
1596 result = -ENODEV;
1597 goto end;
1598 }
1599 1655
1656 sbs->base = (val & 0xff00ull) >> 8;
1600 sbs->device = device; 1657 sbs->device = device;
1601 sbs->smbus = ec_hc->smbus;
1602 1658
1603 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); 1659 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
1604 strcpy(acpi_device_class(device), ACPI_SBS_CLASS); 1660 strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
1605 acpi_driver_data(device) = sbs; 1661 acpi_driver_data(device) = sbs;
1606 1662
1607 sbs->update_time = 0;
1608 sbs->update_time2 = 0;
1609
1610 result = acpi_ac_add(sbs); 1663 result = acpi_ac_add(sbs);
1611 if (result) { 1664 if (result) {
1612 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_ac_add() failed\n")); 1665 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed"));
1613 goto end; 1666 goto end;
1614 } 1667 }
1615 result = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj); 1668 status = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj);
1616 if (ACPI_FAILURE(result)) { 1669 if (status) {
1617 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1670 ACPI_EXCEPTION((AE_INFO, status,
1618 "acpi_evaluate_integer() failed\n")); 1671 "acpi_evaluate_integer() failed"));
1619 result = -EIO; 1672 result = -EIO;
1620 goto end; 1673 goto end;
1621 } 1674 }
1622
1623 if (sbs_obj > 0) { 1675 if (sbs_obj > 0) {
1624 result = acpi_sbsm_get_info(sbs); 1676 result = acpi_sbsm_get_info(sbs);
1625 if (result) { 1677 if (result) {
1626 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1678 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1627 "acpi_sbsm_get_info() failed\n")); 1679 "acpi_sbsm_get_info() failed"));
1628 goto end; 1680 goto end;
1629 } 1681 }
1630 sbs->sbsm_present = 1; 1682 sbs->sbsm_present = 1;
1631 } 1683 }
1684
1632 if (sbs->sbsm_present == 0) { 1685 if (sbs->sbsm_present == 0) {
1633 result = acpi_battery_add(sbs, 0); 1686 result = acpi_battery_add(sbs, 0);
1634 if (result) { 1687 if (result) {
1635 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1688 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1636 "acpi_battery_add() failed\n")); 1689 "acpi_battery_add() failed"));
1637 goto end; 1690 goto end;
1638 } 1691 }
1639 } else { 1692 } else {
@@ -1641,9 +1694,8 @@ static int acpi_sbs_add(struct acpi_device *device)
1641 if ((sbs->sbsm_batteries_supported & (1 << id))) { 1694 if ((sbs->sbsm_batteries_supported & (1 << id))) {
1642 result = acpi_battery_add(sbs, id); 1695 result = acpi_battery_add(sbs, id);
1643 if (result) { 1696 if (result) {
1644 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1697 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1645 "acpi_battery_add() " 1698 "acpi_battery_add() failed"));
1646 "failed\n"));
1647 goto end; 1699 goto end;
1648 } 1700 }
1649 } 1701 }
@@ -1653,33 +1705,26 @@ static int acpi_sbs_add(struct acpi_device *device)
1653 sbs->handle = device->handle; 1705 sbs->handle = device->handle;
1654 1706
1655 init_timer(&sbs->update_timer); 1707 init_timer(&sbs->update_timer);
1656 if (update_mode == QUEUE_UPDATE_MODE) { 1708 result = acpi_check_update_proc(sbs);
1657 status = acpi_os_execute(OSL_GPE_HANDLER, 1709 if (result)
1658 acpi_sbs_update_queue, sbs); 1710 goto end;
1659 if (status != AE_OK) {
1660 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1661 "acpi_os_execute() failed\n"));
1662 }
1663 }
1664 sbs->update_time = update_time;
1665 sbs->update_time2 = update_time2;
1666
1667 printk(KERN_INFO PREFIX "%s [%s]\n",
1668 acpi_device_name(device), acpi_device_bid(device));
1669 1711
1670 end: 1712 end:
1713
1714 sbs_mutex_unlock(sbs);
1715
1671 if (result) { 1716 if (result) {
1672 remove_result = acpi_sbs_remove(device, 0); 1717 remove_result = acpi_sbs_remove(device, 0);
1673 if (remove_result) { 1718 if (remove_result) {
1674 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1719 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1675 "acpi_sbs_remove() failed\n")); 1720 "acpi_sbs_remove() failed"));
1676 } 1721 }
1677 } 1722 }
1678 1723
1679 return result; 1724 return result;
1680} 1725}
1681 1726
1682int acpi_sbs_remove(struct acpi_device *device, int type) 1727static int acpi_sbs_remove(struct acpi_device *device, int type)
1683{ 1728{
1684 struct acpi_sbs *sbs; 1729 struct acpi_sbs *sbs;
1685 int id; 1730 int id;
@@ -1688,15 +1733,14 @@ int acpi_sbs_remove(struct acpi_device *device, int type)
1688 return -EINVAL; 1733 return -EINVAL;
1689 } 1734 }
1690 1735
1691 sbs = (struct acpi_sbs *)acpi_driver_data(device); 1736 sbs = acpi_driver_data(device);
1692
1693 if (!sbs) { 1737 if (!sbs) {
1694 return -EINVAL; 1738 return -EINVAL;
1695 } 1739 }
1696 1740
1741 sbs_mutex_lock(sbs);
1742
1697 sbs->zombie = 1; 1743 sbs->zombie = 1;
1698 sbs->update_time = 0;
1699 sbs->update_time2 = 0;
1700 del_timer_sync(&sbs->update_timer); 1744 del_timer_sync(&sbs->update_timer);
1701 acpi_os_wait_events_complete(NULL); 1745 acpi_os_wait_events_complete(NULL);
1702 del_timer_sync(&sbs->update_timer); 1746 del_timer_sync(&sbs->update_timer);
@@ -1707,11 +1751,41 @@ int acpi_sbs_remove(struct acpi_device *device, int type)
1707 1751
1708 acpi_ac_remove(sbs); 1752 acpi_ac_remove(sbs);
1709 1753
1754 sbs_mutex_unlock(sbs);
1755
1756 mutex_destroy(&sbs->mutex);
1757
1710 kfree(sbs); 1758 kfree(sbs);
1711 1759
1712 return 0; 1760 return 0;
1713} 1761}
1714 1762
1763static void acpi_sbs_rmdirs(void)
1764{
1765 if (acpi_ac_dir) {
1766 acpi_unlock_ac_dir(acpi_ac_dir);
1767 acpi_ac_dir = NULL;
1768 }
1769 if (acpi_battery_dir) {
1770 acpi_unlock_battery_dir(acpi_battery_dir);
1771 acpi_battery_dir = NULL;
1772 }
1773}
1774
1775static int acpi_sbs_resume(struct acpi_device *device)
1776{
1777 struct acpi_sbs *sbs;
1778
1779 if (!device)
1780 return -EINVAL;
1781
1782 sbs = device->driver_data;
1783
1784 sbs->run_cnt = 0;
1785
1786 return 0;
1787}
1788
1715static int __init acpi_sbs_init(void) 1789static int __init acpi_sbs_init(void)
1716{ 1790{
1717 int result = 0; 1791 int result = 0;
@@ -1719,35 +1793,34 @@ static int __init acpi_sbs_init(void)
1719 if (acpi_disabled) 1793 if (acpi_disabled)
1720 return -ENODEV; 1794 return -ENODEV;
1721 1795
1722 init_MUTEX(&sbs_sem);
1723
1724 if (capacity_mode != DEF_CAPACITY_UNIT 1796 if (capacity_mode != DEF_CAPACITY_UNIT
1725 && capacity_mode != MAH_CAPACITY_UNIT 1797 && capacity_mode != MAH_CAPACITY_UNIT
1726 && capacity_mode != MWH_CAPACITY_UNIT) { 1798 && capacity_mode != MWH_CAPACITY_UNIT) {
1727 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_sbs_init: " 1799 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1728 "invalid capacity_mode = %d\n", 1800 "invalid capacity_mode = %d", capacity_mode));
1729 capacity_mode));
1730 return -EINVAL; 1801 return -EINVAL;
1731 } 1802 }
1732 1803
1733 acpi_ac_dir = acpi_lock_ac_dir(); 1804 acpi_ac_dir = acpi_lock_ac_dir();
1734 if (!acpi_ac_dir) { 1805 if (!acpi_ac_dir) {
1735 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1806 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1736 "acpi_lock_ac_dir() failed\n")); 1807 "acpi_lock_ac_dir() failed"));
1737 return -ENODEV; 1808 return -ENODEV;
1738 } 1809 }
1739 1810
1740 acpi_battery_dir = acpi_lock_battery_dir(); 1811 acpi_battery_dir = acpi_lock_battery_dir();
1741 if (!acpi_battery_dir) { 1812 if (!acpi_battery_dir) {
1742 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1813 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1743 "acpi_lock_battery_dir() failed\n")); 1814 "acpi_lock_battery_dir() failed"));
1815 acpi_sbs_rmdirs();
1744 return -ENODEV; 1816 return -ENODEV;
1745 } 1817 }
1746 1818
1747 result = acpi_bus_register_driver(&acpi_sbs_driver); 1819 result = acpi_bus_register_driver(&acpi_sbs_driver);
1748 if (result < 0) { 1820 if (result < 0) {
1749 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1821 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1750 "acpi_bus_register_driver() failed\n")); 1822 "acpi_bus_register_driver() failed"));
1823 acpi_sbs_rmdirs();
1751 return -ENODEV; 1824 return -ENODEV;
1752 } 1825 }
1753 1826
@@ -1756,13 +1829,9 @@ static int __init acpi_sbs_init(void)
1756 1829
1757static void __exit acpi_sbs_exit(void) 1830static void __exit acpi_sbs_exit(void)
1758{ 1831{
1759
1760 acpi_bus_unregister_driver(&acpi_sbs_driver); 1832 acpi_bus_unregister_driver(&acpi_sbs_driver);
1761 1833
1762 acpi_unlock_ac_dir(acpi_ac_dir); 1834 acpi_sbs_rmdirs();
1763 acpi_ac_dir = NULL;
1764 acpi_unlock_battery_dir(acpi_battery_dir);
1765 acpi_battery_dir = NULL;
1766 1835
1767 return; 1836 return;
1768} 1837}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index bb0e0da39fb1..d80dd84e5bfd 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1068,7 +1068,9 @@ acpi_add_single_object(struct acpi_device **child,
1068 } 1068 }
1069 break; 1069 break;
1070 default: 1070 default:
1071 STRUCT_TO_INT(device->status) = 0x0F; 1071 STRUCT_TO_INT(device->status) =
1072 ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
1073 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
1072 break; 1074 break;
1073 } 1075 }
1074 1076
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index ccc11b33d89c..2d912b71e543 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -350,21 +350,31 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
350{ 350{
351 struct list_head *node, *next; 351 struct list_head *node, *next;
352 352
353 seq_printf(seq, "Device Sleep state Status\n"); 353 seq_printf(seq, "Device\tS-state\t Status Sysfs node\n");
354 354
355 spin_lock(&acpi_device_lock); 355 spin_lock(&acpi_device_lock);
356 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 356 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
357 struct acpi_device *dev = 357 struct acpi_device *dev =
358 container_of(node, struct acpi_device, wakeup_list); 358 container_of(node, struct acpi_device, wakeup_list);
359 struct device *ldev;
359 360
360 if (!dev->wakeup.flags.valid) 361 if (!dev->wakeup.flags.valid)
361 continue; 362 continue;
362 spin_unlock(&acpi_device_lock); 363 spin_unlock(&acpi_device_lock);
363 seq_printf(seq, "%4s %4d %s%8s\n", 364
365 ldev = acpi_get_physical_device(dev->handle);
366 seq_printf(seq, "%s\t S%d\t%c%-8s ",
364 dev->pnp.bus_id, 367 dev->pnp.bus_id,
365 (u32) dev->wakeup.sleep_state, 368 (u32) dev->wakeup.sleep_state,
366 dev->wakeup.flags.run_wake ? "*" : "", 369 dev->wakeup.flags.run_wake ? '*' : ' ',
367 dev->wakeup.state.enabled ? "enabled" : "disabled"); 370 dev->wakeup.state.enabled ? "enabled" : "disabled");
371 if (ldev)
372 seq_printf(seq, "%s:%s",
373 ldev->bus ? ldev->bus->name : "no-bus",
374 ldev->bus_id);
375 seq_printf(seq, "\n");
376 put_device(ldev);
377
368 spin_lock(&acpi_device_lock); 378 spin_lock(&acpi_device_lock);
369 } 379 }
370 spin_unlock(&acpi_device_lock); 380 spin_unlock(&acpi_device_lock);
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
index 807c7116e94b..1db833eb2417 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/drivers/acpi/tables/tbfadt.c
@@ -347,6 +347,18 @@ static void acpi_tb_convert_fadt(void)
347 acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; 347 acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id;
348 348
349 } 349 }
350
351 /*
352 * For ACPI 1.0 FADTs, ensure that reserved fields (which should be zero)
353 * are indeed zero. This will workaround BIOSs that inadvertently placed
354 * values in these fields.
355 */
356 if (acpi_gbl_FADT.header.revision < 3) {
357 acpi_gbl_FADT.preferred_profile = 0;
358 acpi_gbl_FADT.pstate_control = 0;
359 acpi_gbl_FADT.cst_control = 0;
360 acpi_gbl_FADT.boot_flags = 0;
361 }
350} 362}
351 363
352/****************************************************************************** 364/******************************************************************************
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 78237577b05a..3ef593a9015f 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * Sony Programmable I/O Control Device driver for VAIO 2 * Sony Programmable I/O Control Device driver for VAIO
3 * 3 *
4 * Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
5 *
4 * Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net> 6 * Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net>
5 * 7 *
6 * Copyright (C) 2005 Narayanan R S <nars@kadamba.org> 8 * Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
@@ -95,6 +97,11 @@ module_param(useinput, int, 0444);
95MODULE_PARM_DESC(useinput, 97MODULE_PARM_DESC(useinput,
96 "set this if you would like sonypi to feed events to the input subsystem"); 98 "set this if you would like sonypi to feed events to the input subsystem");
97 99
100static int check_ioport = 1;
101module_param(check_ioport, int, 0444);
102MODULE_PARM_DESC(check_ioport,
103 "set this to 0 if you think the automatic ioport check for sony-laptop is wrong");
104
98#define SONYPI_DEVICE_MODEL_TYPE1 1 105#define SONYPI_DEVICE_MODEL_TYPE1 1
99#define SONYPI_DEVICE_MODEL_TYPE2 2 106#define SONYPI_DEVICE_MODEL_TYPE2 2
100#define SONYPI_DEVICE_MODEL_TYPE3 3 107#define SONYPI_DEVICE_MODEL_TYPE3 3
@@ -477,7 +484,7 @@ static struct sonypi_device {
477 u16 evtype_offset; 484 u16 evtype_offset;
478 int camera_power; 485 int camera_power;
479 int bluetooth_power; 486 int bluetooth_power;
480 struct semaphore lock; 487 struct mutex lock;
481 struct kfifo *fifo; 488 struct kfifo *fifo;
482 spinlock_t fifo_lock; 489 spinlock_t fifo_lock;
483 wait_queue_head_t fifo_proc_list; 490 wait_queue_head_t fifo_proc_list;
@@ -884,7 +891,7 @@ int sonypi_camera_command(int command, u8 value)
884 if (!camera) 891 if (!camera)
885 return -EIO; 892 return -EIO;
886 893
887 down(&sonypi_device.lock); 894 mutex_lock(&sonypi_device.lock);
888 895
889 switch (command) { 896 switch (command) {
890 case SONYPI_COMMAND_SETCAMERA: 897 case SONYPI_COMMAND_SETCAMERA:
@@ -919,7 +926,7 @@ int sonypi_camera_command(int command, u8 value)
919 command); 926 command);
920 break; 927 break;
921 } 928 }
922 up(&sonypi_device.lock); 929 mutex_unlock(&sonypi_device.lock);
923 return 0; 930 return 0;
924} 931}
925 932
@@ -938,20 +945,20 @@ static int sonypi_misc_fasync(int fd, struct file *filp, int on)
938static int sonypi_misc_release(struct inode *inode, struct file *file) 945static int sonypi_misc_release(struct inode *inode, struct file *file)
939{ 946{
940 sonypi_misc_fasync(-1, file, 0); 947 sonypi_misc_fasync(-1, file, 0);
941 down(&sonypi_device.lock); 948 mutex_lock(&sonypi_device.lock);
942 sonypi_device.open_count--; 949 sonypi_device.open_count--;
943 up(&sonypi_device.lock); 950 mutex_unlock(&sonypi_device.lock);
944 return 0; 951 return 0;
945} 952}
946 953
947static int sonypi_misc_open(struct inode *inode, struct file *file) 954static int sonypi_misc_open(struct inode *inode, struct file *file)
948{ 955{
949 down(&sonypi_device.lock); 956 mutex_lock(&sonypi_device.lock);
950 /* Flush input queue on first open */ 957 /* Flush input queue on first open */
951 if (!sonypi_device.open_count) 958 if (!sonypi_device.open_count)
952 kfifo_reset(sonypi_device.fifo); 959 kfifo_reset(sonypi_device.fifo);
953 sonypi_device.open_count++; 960 sonypi_device.open_count++;
954 up(&sonypi_device.lock); 961 mutex_unlock(&sonypi_device.lock);
955 return 0; 962 return 0;
956} 963}
957 964
@@ -1001,7 +1008,7 @@ static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
1001 u8 val8; 1008 u8 val8;
1002 u16 val16; 1009 u16 val16;
1003 1010
1004 down(&sonypi_device.lock); 1011 mutex_lock(&sonypi_device.lock);
1005 switch (cmd) { 1012 switch (cmd) {
1006 case SONYPI_IOCGBRT: 1013 case SONYPI_IOCGBRT:
1007 if (sonypi_ec_read(SONYPI_LCD_LIGHT, &val8)) { 1014 if (sonypi_ec_read(SONYPI_LCD_LIGHT, &val8)) {
@@ -1101,7 +1108,7 @@ static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
1101 default: 1108 default:
1102 ret = -EINVAL; 1109 ret = -EINVAL;
1103 } 1110 }
1104 up(&sonypi_device.lock); 1111 mutex_unlock(&sonypi_device.lock);
1105 return ret; 1112 return ret;
1106} 1113}
1107 1114
@@ -1260,6 +1267,28 @@ static int __devinit sonypi_create_input_devices(void)
1260static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, 1267static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
1261 const struct sonypi_ioport_list *ioport_list) 1268 const struct sonypi_ioport_list *ioport_list)
1262{ 1269{
1270 /* try to detect if sony-laptop is being used and thus
1271 * has already requested one of the known ioports.
1272 * As in the deprecated check_region this is racy has we have
1273 * multiple ioports available and one of them can be requested
1274 * between this check and the subsequent request. Anyway, as an
1275 * attempt to be some more user-friendly as we currently are,
1276 * this is enough.
1277 */
1278 const struct sonypi_ioport_list *check = ioport_list;
1279 while (check_ioport && check->port1) {
1280 if (!request_region(check->port1,
1281 sonypi_device.region_size,
1282 "Sony Programable I/O Device Check")) {
1283 printk(KERN_ERR "sonypi: ioport 0x%.4x busy, using sony-laptop? "
1284 "if not use check_ioport=0\n",
1285 check->port1);
1286 return -EBUSY;
1287 }
1288 release_region(check->port1, sonypi_device.region_size);
1289 check++;
1290 }
1291
1263 while (ioport_list->port1) { 1292 while (ioport_list->port1) {
1264 1293
1265 if (request_region(ioport_list->port1, 1294 if (request_region(ioport_list->port1,
@@ -1321,6 +1350,10 @@ static int __devinit sonypi_probe(struct platform_device *dev)
1321 struct pci_dev *pcidev; 1350 struct pci_dev *pcidev;
1322 int error; 1351 int error;
1323 1352
1353 printk(KERN_WARNING "sonypi: please try the sony-laptop module instead "
1354 "and report failures, see also "
1355 "http://www.linux.it/~malattia/wiki/index.php/Sony_drivers\n");
1356
1324 spin_lock_init(&sonypi_device.fifo_lock); 1357 spin_lock_init(&sonypi_device.fifo_lock);
1325 sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, 1358 sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
1326 &sonypi_device.fifo_lock); 1359 &sonypi_device.fifo_lock);
@@ -1330,7 +1363,7 @@ static int __devinit sonypi_probe(struct platform_device *dev)
1330 } 1363 }
1331 1364
1332 init_waitqueue_head(&sonypi_device.fifo_proc_list); 1365 init_waitqueue_head(&sonypi_device.fifo_proc_list);
1333 init_MUTEX(&sonypi_device.lock); 1366 mutex_init(&sonypi_device.lock);
1334 sonypi_device.bluetooth_power = -1; 1367 sonypi_device.bluetooth_power = -1;
1335 1368
1336 if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1369 if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 5ac309ee7f05..5cfcff532545 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -26,7 +26,7 @@
26/* 26/*
27 * The I/O port the PMTMR resides at. 27 * The I/O port the PMTMR resides at.
28 * The location is detected during setup_arch(), 28 * The location is detected during setup_arch(),
29 * in arch/i386/acpi/boot.c 29 * in arch/i386/kernel/acpi/boot.c
30 */ 30 */
31u32 pmtmr_ioport __read_mostly; 31u32 pmtmr_ioport __read_mostly;
32 32
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 639e8b6c35b1..bc773781993a 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -577,14 +577,14 @@ config VIDEO_ZORAN_AVS6EYES
577 577
578config VIDEO_MEYE 578config VIDEO_MEYE
579 tristate "Sony Vaio Picturebook Motion Eye Video For Linux" 579 tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
580 depends on PCI && SONYPI && VIDEO_V4L1 580 depends on PCI && SONY_LAPTOP && VIDEO_V4L1
581 ---help--- 581 ---help---
582 This is the video4linux driver for the Motion Eye camera found 582 This is the video4linux driver for the Motion Eye camera found
583 in the Vaio Picturebook laptops. Please read the material in 583 in the Vaio Picturebook laptops. Please read the material in
584 <file:Documentation/video4linux/meye.txt> for more information. 584 <file:Documentation/video4linux/meye.txt> for more information.
585 585
586 If you say Y or M here, you need to say Y or M to "Sony Programmable 586 If you say Y or M here, you need to say Y or M to "Sony Laptop
587 I/O Control Device" in the character device section. 587 Extras" in the misc device section.
588 588
589 To compile this driver as a module, choose M here: the 589 To compile this driver as a module, choose M here: the
590 module will be called meye. 590 module will be called meye.
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 98681da5e3b9..664aba8b4d85 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -925,13 +925,13 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
925 if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV) 925 if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV)
926 return -EINVAL; 926 return -EINVAL;
927 mutex_lock(&meye.lock); 927 mutex_lock(&meye.lock);
928 sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, 928 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS,
929 p->brightness >> 10); 929 p->brightness >> 10);
930 sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, 930 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE,
931 p->hue >> 10); 931 p->hue >> 10);
932 sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, 932 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR,
933 p->colour >> 10); 933 p->colour >> 10);
934 sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, 934 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST,
935 p->contrast >> 10); 935 p->contrast >> 10);
936 meye.picture = *p; 936 meye.picture = *p;
937 mutex_unlock(&meye.lock); 937 mutex_unlock(&meye.lock);
@@ -1043,11 +1043,11 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
1043 meye.params.quality != jp->quality) 1043 meye.params.quality != jp->quality)
1044 mchip_hic_stop(); /* need restart */ 1044 mchip_hic_stop(); /* need restart */
1045 meye.params = *jp; 1045 meye.params = *jp;
1046 sonypi_camera_command(SONYPI_COMMAND_SETCAMERASHARPNESS, 1046 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
1047 meye.params.sharpness); 1047 meye.params.sharpness);
1048 sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 1048 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
1049 meye.params.agc); 1049 meye.params.agc);
1050 sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, 1050 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
1051 meye.params.picture); 1051 meye.params.picture);
1052 mutex_unlock(&meye.lock); 1052 mutex_unlock(&meye.lock);
1053 break; 1053 break;
@@ -1287,38 +1287,38 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
1287 mutex_lock(&meye.lock); 1287 mutex_lock(&meye.lock);
1288 switch (c->id) { 1288 switch (c->id) {
1289 case V4L2_CID_BRIGHTNESS: 1289 case V4L2_CID_BRIGHTNESS:
1290 sonypi_camera_command( 1290 sony_pic_camera_command(
1291 SONYPI_COMMAND_SETCAMERABRIGHTNESS, c->value); 1291 SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
1292 meye.picture.brightness = c->value << 10; 1292 meye.picture.brightness = c->value << 10;
1293 break; 1293 break;
1294 case V4L2_CID_HUE: 1294 case V4L2_CID_HUE:
1295 sonypi_camera_command( 1295 sony_pic_camera_command(
1296 SONYPI_COMMAND_SETCAMERAHUE, c->value); 1296 SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
1297 meye.picture.hue = c->value << 10; 1297 meye.picture.hue = c->value << 10;
1298 break; 1298 break;
1299 case V4L2_CID_CONTRAST: 1299 case V4L2_CID_CONTRAST:
1300 sonypi_camera_command( 1300 sony_pic_camera_command(
1301 SONYPI_COMMAND_SETCAMERACONTRAST, c->value); 1301 SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
1302 meye.picture.contrast = c->value << 10; 1302 meye.picture.contrast = c->value << 10;
1303 break; 1303 break;
1304 case V4L2_CID_SATURATION: 1304 case V4L2_CID_SATURATION:
1305 sonypi_camera_command( 1305 sony_pic_camera_command(
1306 SONYPI_COMMAND_SETCAMERACOLOR, c->value); 1306 SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
1307 meye.picture.colour = c->value << 10; 1307 meye.picture.colour = c->value << 10;
1308 break; 1308 break;
1309 case V4L2_CID_AGC: 1309 case V4L2_CID_AGC:
1310 sonypi_camera_command( 1310 sony_pic_camera_command(
1311 SONYPI_COMMAND_SETCAMERAAGC, c->value); 1311 SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
1312 meye.params.agc = c->value; 1312 meye.params.agc = c->value;
1313 break; 1313 break;
1314 case V4L2_CID_SHARPNESS: 1314 case V4L2_CID_SHARPNESS:
1315 sonypi_camera_command( 1315 sony_pic_camera_command(
1316 SONYPI_COMMAND_SETCAMERASHARPNESS, c->value); 1316 SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
1317 meye.params.sharpness = c->value; 1317 meye.params.sharpness = c->value;
1318 break; 1318 break;
1319 case V4L2_CID_PICTURE: 1319 case V4L2_CID_PICTURE:
1320 sonypi_camera_command( 1320 sony_pic_camera_command(
1321 SONYPI_COMMAND_SETCAMERAPICTURE, c->value); 1321 SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
1322 meye.params.picture = c->value; 1322 meye.params.picture = c->value;
1323 break; 1323 break;
1324 case V4L2_CID_JPEGQUAL: 1324 case V4L2_CID_JPEGQUAL:
@@ -1848,7 +1848,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
1848 memcpy(meye.video_dev, &meye_template, sizeof(meye_template)); 1848 memcpy(meye.video_dev, &meye_template, sizeof(meye_template));
1849 meye.video_dev->dev = &meye.mchip_dev->dev; 1849 meye.video_dev->dev = &meye.mchip_dev->dev;
1850 1850
1851 if ((ret = sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 1))) { 1851 if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
1852 printk(KERN_ERR "meye: unable to power on the camera\n"); 1852 printk(KERN_ERR "meye: unable to power on the camera\n");
1853 printk(KERN_ERR "meye: did you enable the camera in " 1853 printk(KERN_ERR "meye: did you enable the camera in "
1854 "sonypi using the module options ?\n"); 1854 "sonypi using the module options ?\n");
@@ -1928,13 +1928,13 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
1928 meye.params.picture = 0; 1928 meye.params.picture = 0;
1929 meye.params.framerate = 0; 1929 meye.params.framerate = 0;
1930 1930
1931 sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, 32); 1931 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, 32);
1932 sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, 32); 1932 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, 32);
1933 sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, 32); 1933 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, 32);
1934 sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, 32); 1934 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, 32);
1935 sonypi_camera_command(SONYPI_COMMAND_SETCAMERASHARPNESS, 32); 1935 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, 32);
1936 sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, 0); 1936 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
1937 sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 48); 1937 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
1938 1938
1939 printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n", 1939 printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n",
1940 MEYE_DRIVER_VERSION); 1940 MEYE_DRIVER_VERSION);
@@ -1953,7 +1953,7 @@ outremap:
1953outregions: 1953outregions:
1954 pci_disable_device(meye.mchip_dev); 1954 pci_disable_device(meye.mchip_dev);
1955outenabledev: 1955outenabledev:
1956 sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); 1956 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
1957outsonypienable: 1957outsonypienable:
1958 kfifo_free(meye.doneq); 1958 kfifo_free(meye.doneq);
1959outkfifoalloc2: 1959outkfifoalloc2:
@@ -1986,7 +1986,7 @@ static void __devexit meye_remove(struct pci_dev *pcidev)
1986 1986
1987 pci_disable_device(meye.mchip_dev); 1987 pci_disable_device(meye.mchip_dev);
1988 1988
1989 sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); 1989 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
1990 1990
1991 kfifo_free(meye.doneq); 1991 kfifo_free(meye.doneq);
1992 kfifo_free(meye.grabq); 1992 kfifo_free(meye.grabq);
diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h
index ea107cb5c845..323d0074120d 100644
--- a/drivers/media/video/meye.h
+++ b/drivers/media/video/meye.h
@@ -255,7 +255,7 @@
255/****************************************************************************/ 255/****************************************************************************/
256 256
257/* Sony Programmable I/O Controller for accessing the camera commands */ 257/* Sony Programmable I/O Controller for accessing the camera commands */
258#include <linux/sonypi.h> 258#include <linux/sony-laptop.h>
259 259
260/* private API definitions */ 260/* private API definitions */
261#include <linux/meye.h> 261#include <linux/meye.h>
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 80b199fa0aa9..a3c525b2616a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -112,14 +112,70 @@ config SONY_LAPTOP
112 depends on X86 && ACPI 112 depends on X86 && ACPI
113 select BACKLIGHT_CLASS_DEVICE 113 select BACKLIGHT_CLASS_DEVICE
114 ---help--- 114 ---help---
115 This mini-driver drives the SNC device present in the ACPI BIOS of 115 This mini-driver drives the SNC and SPIC devices present in the ACPI
116 the Sony Vaio laptops. 116 BIOS of the Sony Vaio laptops.
117 117
118 It gives access to some extra laptop functionalities. In its current 118 It gives access to some extra laptop functionalities like Bluetooth,
119 form, this driver let the user set or query the screen brightness 119 screen brightness control, Fn keys and allows powering on/off some
120 through the backlight subsystem and remove/apply power to some
121 devices. 120 devices.
122 121
123 Read <file:Documentation/sony-laptop.txt> for more information. 122 Read <file:Documentation/sony-laptop.txt> for more information.
124 123
124config SONY_LAPTOP_OLD
125 bool "Sonypi compatibility"
126 depends on SONY_LAPTOP
127 ---help---
128 Build the sonypi driver compatibility code into the sony-laptop driver.
129
130config THINKPAD_ACPI
131 tristate "ThinkPad ACPI Laptop Extras"
132 depends on X86 && ACPI
133 select BACKLIGHT_CLASS_DEVICE
134 select HWMON
135 ---help---
136 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
137 support for Fn-Fx key combinations, Bluetooth control, video
138 output switching, ThinkLight control, UltraBay eject and more.
139 For more information about this driver see
140 <file:Documentation/thinkpad-acpi.txt> and <http://ibm-acpi.sf.net/> .
141
142 This driver was formely known as ibm-acpi.
143
144 If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
145
146config THINKPAD_ACPI_DEBUG
147 bool "Verbose debug mode"
148 depends on THINKPAD_ACPI
149 default n
150 ---help---
151 Enables extra debugging information, at the expense of a slightly
152 increase in driver size.
153
154 If you are not sure, say N here.
155
156config THINKPAD_ACPI_DOCK
157 bool "Legacy Docking Station Support"
158 depends on THINKPAD_ACPI
159 depends on ACPI_DOCK=n
160 default n
161 ---help---
162 Allows the thinkpad_acpi driver to handle docking station events.
163 This support was made obsolete by the generic ACPI docking station
164 support (CONFIG_ACPI_DOCK). It will allow locking and removing the
165 laptop from the docking station, but will not properly connect PCI
166 devices.
167
168 If you are not sure, say N here.
169
170config THINKPAD_ACPI_BAY
171 bool "Legacy Removable Bay Support"
172 depends on THINKPAD_ACPI
173 default y
174 ---help---
175 Allows the thinkpad_acpi driver to handle removable bays. It will
176 eletrically disable the device in the bay, and also generate
177 notifications when the bay lever is ejected or inserted.
178
179 If you are not sure, say Y here.
180
125endmenu 181endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 7793ccd79049..e32516459138 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_TIFM_CORE) += tifm_core.o
12obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o 12obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
13obj-$(CONFIG_SGI_IOC4) += ioc4.o 13obj-$(CONFIG_SGI_IOC4) += ioc4.o
14obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o 14obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
15obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 4b232124a1ab..65c32a95e121 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * 4 *
5 * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor 5 * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
6 * Copyright (C) 2006 Corentin Chary 6 * Copyright (C) 2006-2007 Corentin Chary
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -48,7 +48,7 @@
48#include <acpi/acpi_bus.h> 48#include <acpi/acpi_bus.h>
49#include <asm/uaccess.h> 49#include <asm/uaccess.h>
50 50
51#define ASUS_LAPTOP_VERSION "0.40" 51#define ASUS_LAPTOP_VERSION "0.41"
52 52
53#define ASUS_HOTK_NAME "Asus Laptop Support" 53#define ASUS_HOTK_NAME "Asus Laptop Support"
54#define ASUS_HOTK_CLASS "hotkey" 54#define ASUS_HOTK_CLASS "hotkey"
@@ -81,7 +81,8 @@
81#define TLED_ON 0x08 //touchpad LED 81#define TLED_ON 0x08 //touchpad LED
82#define RLED_ON 0x10 //Record LED 82#define RLED_ON 0x10 //Record LED
83#define PLED_ON 0x20 //Phone LED 83#define PLED_ON 0x20 //Phone LED
84#define LCD_ON 0x40 //LCD backlight 84#define GLED_ON 0x40 //Gaming LED
85#define LCD_ON 0x80 //LCD backlight
85 86
86#define ASUS_LOG ASUS_HOTK_FILE ": " 87#define ASUS_LOG ASUS_HOTK_FILE ": "
87#define ASUS_ERR KERN_ERR ASUS_LOG 88#define ASUS_ERR KERN_ERR ASUS_LOG
@@ -94,6 +95,19 @@ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary");
94MODULE_DESCRIPTION(ASUS_HOTK_NAME); 95MODULE_DESCRIPTION(ASUS_HOTK_NAME);
95MODULE_LICENSE("GPL"); 96MODULE_LICENSE("GPL");
96 97
98/* WAPF defines the behavior of the Fn+Fx wlan key
99 * The significance of values is yet to be found, but
100 * most of the time:
101 * 0x0 will do nothing
102 * 0x1 will allow to control the device with Fn+Fx key.
103 * 0x4 will send an ACPI event (0x88) while pressing the Fn+Fx key
104 * 0x5 like 0x1 or 0x4
105 * So, if something doesn't work as you want, just try other values =)
106 */
107static uint wapf = 1;
108module_param(wapf, uint, 0644);
109MODULE_PARM_DESC(wapf, "WAPF value");
110
97#define ASUS_HANDLE(object, paths...) \ 111#define ASUS_HANDLE(object, paths...) \
98 static acpi_handle object##_handle = NULL; \ 112 static acpi_handle object##_handle = NULL; \
99 static char *object##_paths[] = { paths } 113 static char *object##_paths[] = { paths }
@@ -103,6 +117,7 @@ ASUS_HANDLE(mled_set, ASUS_HOTK_PREFIX "MLED");
103ASUS_HANDLE(tled_set, ASUS_HOTK_PREFIX "TLED"); 117ASUS_HANDLE(tled_set, ASUS_HOTK_PREFIX "TLED");
104ASUS_HANDLE(rled_set, ASUS_HOTK_PREFIX "RLED"); /* W1JC */ 118ASUS_HANDLE(rled_set, ASUS_HOTK_PREFIX "RLED"); /* W1JC */
105ASUS_HANDLE(pled_set, ASUS_HOTK_PREFIX "PLED"); /* A7J */ 119ASUS_HANDLE(pled_set, ASUS_HOTK_PREFIX "PLED"); /* A7J */
120ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED"); /* G1, G2 (probably) */
106 121
107/* LEDD */ 122/* LEDD */
108ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); 123ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM");
@@ -221,6 +236,7 @@ ASUS_LED(mled, "mail");
221ASUS_LED(tled, "touchpad"); 236ASUS_LED(tled, "touchpad");
222ASUS_LED(rled, "record"); 237ASUS_LED(rled, "record");
223ASUS_LED(pled, "phone"); 238ASUS_LED(pled, "phone");
239ASUS_LED(gled, "gaming");
224 240
225/* 241/*
226 * This function evaluates an ACPI method, given an int as parameter, the 242 * This function evaluates an ACPI method, given an int as parameter, the
@@ -245,32 +261,19 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
245 return (status == AE_OK); 261 return (status == AE_OK);
246} 262}
247 263
248static int read_acpi_int(acpi_handle handle, const char *method, int *val,
249 struct acpi_object_list *params)
250{
251 struct acpi_buffer output;
252 union acpi_object out_obj;
253 acpi_status status;
254
255 output.length = sizeof(out_obj);
256 output.pointer = &out_obj;
257
258 status = acpi_evaluate_object(handle, (char *)method, params, &output);
259 *val = out_obj.integer.value;
260 return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
261}
262
263static int read_wireless_status(int mask) 264static int read_wireless_status(int mask)
264{ 265{
265 int status; 266 ulong status;
267 acpi_status rv = AE_OK;
266 268
267 if (!wireless_status_handle) 269 if (!wireless_status_handle)
268 return (hotk->status & mask) ? 1 : 0; 270 return (hotk->status & mask) ? 1 : 0;
269 271
270 if (read_acpi_int(wireless_status_handle, NULL, &status, NULL)) { 272 rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status);
271 return (status & mask) ? 1 : 0; 273 if (ACPI_FAILURE(rv))
272 } else
273 printk(ASUS_WARNING "Error reading Wireless status\n"); 274 printk(ASUS_WARNING "Error reading Wireless status\n");
275 else
276 return (status & mask) ? 1 : 0;
274 277
275 return (hotk->status & mask) ? 1 : 0; 278 return (hotk->status & mask) ? 1 : 0;
276} 279}
@@ -285,19 +288,28 @@ static int read_status(int mask)
285 return (hotk->status & mask) ? 1 : 0; 288 return (hotk->status & mask) ? 1 : 0;
286} 289}
287 290
288static void write_status(acpi_handle handle, int out, int mask, int invert) 291static void write_status(acpi_handle handle, int out, int mask)
289{ 292{
290 hotk->status = (out) ? (hotk->status | mask) : (hotk->status & ~mask); 293 hotk->status = (out) ? (hotk->status | mask) : (hotk->status & ~mask);
291 294
292 if (invert) /* invert target value */ 295 switch (mask) {
296 case MLED_ON:
293 out = !out & 0x1; 297 out = !out & 0x1;
298 break;
299 case GLED_ON:
300 out = (out & 0x1) + 1;
301 break;
302 default:
303 out &= 0x1;
304 break;
305 }
294 306
295 if (handle && !write_acpi_int(handle, NULL, out, NULL)) 307 if (handle && !write_acpi_int(handle, NULL, out, NULL))
296 printk(ASUS_WARNING " write failed\n"); 308 printk(ASUS_WARNING " write failed %x\n", mask);
297} 309}
298 310
299/* /sys/class/led handlers */ 311/* /sys/class/led handlers */
300#define ASUS_LED_HANDLER(object, mask, invert) \ 312#define ASUS_LED_HANDLER(object, mask) \
301 static void object##_led_set(struct led_classdev *led_cdev, \ 313 static void object##_led_set(struct led_classdev *led_cdev, \
302 enum led_brightness value) \ 314 enum led_brightness value) \
303 { \ 315 { \
@@ -307,13 +319,14 @@ static void write_status(acpi_handle handle, int out, int mask, int invert)
307 static void object##_led_update(struct work_struct *ignored) \ 319 static void object##_led_update(struct work_struct *ignored) \
308 { \ 320 { \
309 int value = object##_led_wk; \ 321 int value = object##_led_wk; \
310 write_status(object##_set_handle, value, (mask), (invert)); \ 322 write_status(object##_set_handle, value, (mask)); \
311 } 323 }
312 324
313ASUS_LED_HANDLER(mled, MLED_ON, 1); 325ASUS_LED_HANDLER(mled, MLED_ON);
314ASUS_LED_HANDLER(pled, PLED_ON, 0); 326ASUS_LED_HANDLER(pled, PLED_ON);
315ASUS_LED_HANDLER(rled, RLED_ON, 0); 327ASUS_LED_HANDLER(rled, RLED_ON);
316ASUS_LED_HANDLER(tled, TLED_ON, 0); 328ASUS_LED_HANDLER(tled, TLED_ON);
329ASUS_LED_HANDLER(gled, GLED_ON);
317 330
318static int get_lcd_state(void) 331static int get_lcd_state(void)
319{ 332{
@@ -338,7 +351,7 @@ static int set_lcd_state(int value)
338 printk(ASUS_WARNING "Error switching LCD\n"); 351 printk(ASUS_WARNING "Error switching LCD\n");
339 } 352 }
340 353
341 write_status(NULL, lcd, LCD_ON, 0); 354 write_status(NULL, lcd, LCD_ON);
342 return 0; 355 return 0;
343} 356}
344 357
@@ -354,9 +367,11 @@ static void lcd_blank(int blank)
354 367
355static int read_brightness(struct backlight_device *bd) 368static int read_brightness(struct backlight_device *bd)
356{ 369{
357 int value; 370 ulong value;
371 acpi_status rv = AE_OK;
358 372
359 if (!read_acpi_int(brightness_get_handle, NULL, &value, NULL)) 373 rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value);
374 if (ACPI_FAILURE(rv))
360 printk(ASUS_WARNING "Error reading brightness\n"); 375 printk(ASUS_WARNING "Error reading brightness\n");
361 376
362 return value; 377 return value;
@@ -403,8 +418,10 @@ static ssize_t show_infos(struct device *dev,
403 struct device_attribute *attr, char *page) 418 struct device_attribute *attr, char *page)
404{ 419{
405 int len = 0; 420 int len = 0;
406 int temp; 421 ulong temp;
407 char buf[16]; //enough for all info 422 char buf[16]; //enough for all info
423 acpi_status rv = AE_OK;
424
408 /* 425 /*
409 * We use the easy way, we don't care of off and count, so we don't set eof 426 * We use the easy way, we don't care of off and count, so we don't set eof
410 * to 1 427 * to 1
@@ -418,9 +435,10 @@ static ssize_t show_infos(struct device *dev,
418 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. 435 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
419 * The significance of others is yet to be found. 436 * The significance of others is yet to be found.
420 */ 437 */
421 if (read_acpi_int(hotk->handle, "SFUN", &temp, NULL)) 438 rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp);
422 len += 439 if (!ACPI_FAILURE(rv))
423 sprintf(page + len, "SFUN value : 0x%04x\n", temp); 440 len += sprintf(page + len, "SFUN value : 0x%04x\n",
441 (uint) temp);
424 /* 442 /*
425 * Another value for userspace: the ASYM method returns 0x02 for 443 * Another value for userspace: the ASYM method returns 0x02 for
426 * battery low and 0x04 for battery critical, its readings tend to be 444 * battery low and 0x04 for battery critical, its readings tend to be
@@ -428,9 +446,10 @@ static ssize_t show_infos(struct device *dev,
428 * Note: since not all the laptops provide this method, errors are 446 * Note: since not all the laptops provide this method, errors are
429 * silently ignored. 447 * silently ignored.
430 */ 448 */
431 if (read_acpi_int(hotk->handle, "ASYM", &temp, NULL)) 449 rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp);
432 len += 450 if (!ACPI_FAILURE(rv))
433 sprintf(page + len, "ASYM value : 0x%04x\n", temp); 451 len += sprintf(page + len, "ASYM value : 0x%04x\n",
452 (uint) temp);
434 if (asus_info) { 453 if (asus_info) {
435 snprintf(buf, 16, "%d", asus_info->length); 454 snprintf(buf, 16, "%d", asus_info->length);
436 len += sprintf(page + len, "DSDT length : %s\n", buf); 455 len += sprintf(page + len, "DSDT length : %s\n", buf);
@@ -465,7 +484,7 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
465} 484}
466 485
467static ssize_t store_status(const char *buf, size_t count, 486static ssize_t store_status(const char *buf, size_t count,
468 acpi_handle handle, int mask, int invert) 487 acpi_handle handle, int mask)
469{ 488{
470 int rv, value; 489 int rv, value;
471 int out = 0; 490 int out = 0;
@@ -474,7 +493,7 @@ static ssize_t store_status(const char *buf, size_t count,
474 if (rv > 0) 493 if (rv > 0)
475 out = value ? 1 : 0; 494 out = value ? 1 : 0;
476 495
477 write_status(handle, out, mask, invert); 496 write_status(handle, out, mask);
478 497
479 return rv; 498 return rv;
480} 499}
@@ -515,7 +534,7 @@ static ssize_t show_wlan(struct device *dev,
515static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, 534static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
516 const char *buf, size_t count) 535 const char *buf, size_t count)
517{ 536{
518 return store_status(buf, count, wl_switch_handle, WL_ON, 0); 537 return store_status(buf, count, wl_switch_handle, WL_ON);
519} 538}
520 539
521/* 540/*
@@ -531,7 +550,7 @@ static ssize_t store_bluetooth(struct device *dev,
531 struct device_attribute *attr, const char *buf, 550 struct device_attribute *attr, const char *buf,
532 size_t count) 551 size_t count)
533{ 552{
534 return store_status(buf, count, bt_switch_handle, BT_ON, 0); 553 return store_status(buf, count, bt_switch_handle, BT_ON);
535} 554}
536 555
537/* 556/*
@@ -547,12 +566,15 @@ static void set_display(int value)
547 566
548static int read_display(void) 567static int read_display(void)
549{ 568{
550 int value = 0; 569 ulong value = 0;
570 acpi_status rv = AE_OK;
551 571
552 /* In most of the case, we know how to set the display, but sometime 572 /* In most of the case, we know how to set the display, but sometime
553 we can't read it */ 573 we can't read it */
554 if (display_get_handle) { 574 if (display_get_handle) {
555 if (!read_acpi_int(display_get_handle, NULL, &value, NULL)) 575 rv = acpi_evaluate_integer(display_get_handle, NULL,
576 NULL, &value);
577 if (ACPI_FAILURE(rv))
556 printk(ASUS_WARNING "Error reading display status\n"); 578 printk(ASUS_WARNING "Error reading display status\n");
557 } 579 }
558 580
@@ -656,10 +678,10 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
656 * switched 678 * switched
657 */ 679 */
658 if (event == ATKD_LCD_ON) { 680 if (event == ATKD_LCD_ON) {
659 write_status(NULL, 1, LCD_ON, 0); 681 write_status(NULL, 1, LCD_ON);
660 lcd_blank(FB_BLANK_UNBLANK); 682 lcd_blank(FB_BLANK_UNBLANK);
661 } else if (event == ATKD_LCD_OFF) { 683 } else if (event == ATKD_LCD_OFF) {
662 write_status(NULL, 0, LCD_ON, 0); 684 write_status(NULL, 0, LCD_ON);
663 lcd_blank(FB_BLANK_POWERDOWN); 685 lcd_blank(FB_BLANK_POWERDOWN);
664 } 686 }
665 687
@@ -771,7 +793,7 @@ static int asus_hotk_get_info(void)
771{ 793{
772 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 794 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
773 union acpi_object *model = NULL; 795 union acpi_object *model = NULL;
774 int bsts_result, hwrs_result; 796 ulong bsts_result, hwrs_result;
775 char *string = NULL; 797 char *string = NULL;
776 acpi_status status; 798 acpi_status status;
777 799
@@ -794,11 +816,16 @@ static int asus_hotk_get_info(void)
794 } 816 }
795 817
796 /* This needs to be called for some laptops to init properly */ 818 /* This needs to be called for some laptops to init properly */
797 if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result, NULL)) 819 status =
820 acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result);
821 if (ACPI_FAILURE(status))
798 printk(ASUS_WARNING "Error calling BSTS\n"); 822 printk(ASUS_WARNING "Error calling BSTS\n");
799 else if (bsts_result) 823 else if (bsts_result)
800 printk(ASUS_NOTICE "BSTS called, 0x%02x returned\n", 824 printk(ASUS_NOTICE "BSTS called, 0x%02x returned\n",
801 bsts_result); 825 (uint) bsts_result);
826
827 /* This too ... */
828 write_acpi_int(hotk->handle, "CWAP", wapf, NULL);
802 829
803 /* 830 /*
804 * Try to match the object returned by INIT to the specific model. 831 * Try to match the object returned by INIT to the specific model.
@@ -831,6 +858,7 @@ static int asus_hotk_get_info(void)
831 ASUS_HANDLE_INIT(tled_set); 858 ASUS_HANDLE_INIT(tled_set);
832 ASUS_HANDLE_INIT(rled_set); 859 ASUS_HANDLE_INIT(rled_set);
833 ASUS_HANDLE_INIT(pled_set); 860 ASUS_HANDLE_INIT(pled_set);
861 ASUS_HANDLE_INIT(gled_set);
834 862
835 ASUS_HANDLE_INIT(ledd_set); 863 ASUS_HANDLE_INIT(ledd_set);
836 864
@@ -840,7 +868,9 @@ static int asus_hotk_get_info(void)
840 * The significance of others is yet to be found. 868 * The significance of others is yet to be found.
841 * If we don't find the method, we assume the device are present. 869 * If we don't find the method, we assume the device are present.
842 */ 870 */
843 if (!read_acpi_int(hotk->handle, "HRWS", &hwrs_result, NULL)) 871 status =
872 acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &hwrs_result);
873 if (ACPI_FAILURE(status))
844 hwrs_result = WL_HWRS | BT_HWRS; 874 hwrs_result = WL_HWRS | BT_HWRS;
845 875
846 if (hwrs_result & WL_HWRS) 876 if (hwrs_result & WL_HWRS)
@@ -928,11 +958,15 @@ static int asus_hotk_add(struct acpi_device *device)
928 asus_hotk_found = 1; 958 asus_hotk_found = 1;
929 959
930 /* WLED and BLED are on by default */ 960 /* WLED and BLED are on by default */
931 write_status(bt_switch_handle, 1, BT_ON, 0); 961 write_status(bt_switch_handle, 1, BT_ON);
932 write_status(wl_switch_handle, 1, WL_ON, 0); 962 write_status(wl_switch_handle, 1, WL_ON);
963
964 /* If the h/w switch is off, we need to check the real status */
965 write_status(NULL, read_status(BT_ON), BT_ON);
966 write_status(NULL, read_status(WL_ON), WL_ON);
933 967
934 /* LCD Backlight is on by default */ 968 /* LCD Backlight is on by default */
935 write_status(NULL, 1, LCD_ON, 0); 969 write_status(NULL, 1, LCD_ON);
936 970
937 /* LED display is off by default */ 971 /* LED display is off by default */
938 hotk->ledd_status = 0xFFF; 972 hotk->ledd_status = 0xFFF;
@@ -991,6 +1025,7 @@ static void asus_led_exit(void)
991 ASUS_LED_UNREGISTER(tled); 1025 ASUS_LED_UNREGISTER(tled);
992 ASUS_LED_UNREGISTER(pled); 1026 ASUS_LED_UNREGISTER(pled);
993 ASUS_LED_UNREGISTER(rled); 1027 ASUS_LED_UNREGISTER(rled);
1028 ASUS_LED_UNREGISTER(gled);
994 1029
995 destroy_workqueue(led_workqueue); 1030 destroy_workqueue(led_workqueue);
996} 1031}
@@ -1062,6 +1097,10 @@ static int asus_led_init(struct device *dev)
1062 if (rv) 1097 if (rv)
1063 return rv; 1098 return rv;
1064 1099
1100 rv = ASUS_LED_REGISTER(gled, dev);
1101 if (rv)
1102 return rv;
1103
1065 led_workqueue = create_singlethread_workqueue("led_workqueue"); 1104 led_workqueue = create_singlethread_workqueue("led_workqueue");
1066 if (!led_workqueue) 1105 if (!led_workqueue)
1067 return -ENOMEM; 1106 return -ENOMEM;
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index ac708bc2f9f3..c15c1f61bd1b 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * ACPI Sony Notebook Control Driver (SNC) 2 * ACPI Sony Notebook Control Driver (SNC and SPIC)
3 * 3 *
4 * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> 4 * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
5 * Copyright (C) 2007 Mattia Dongili <malattia@linux.it> 5 * Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
@@ -7,6 +7,25 @@
7 * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c 7 * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
8 * which are copyrighted by their respective authors. 8 * which are copyrighted by their respective authors.
9 * 9 *
10 * The SNY6001 driver part is based on the sonypi driver which includes
11 * material from:
12 *
13 * Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net>
14 *
15 * Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
16 *
17 * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
18 *
19 * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
20 *
21 * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
22 *
23 * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
24 *
25 * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
26 *
27 * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
28 *
10 * This program is free software; you can redistribute it and/or modify 29 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 30 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or 31 * the Free Software Foundation; either version 2 of the License, or
@@ -31,40 +50,404 @@
31#include <linux/backlight.h> 50#include <linux/backlight.h>
32#include <linux/platform_device.h> 51#include <linux/platform_device.h>
33#include <linux/err.h> 52#include <linux/err.h>
53#include <linux/dmi.h>
54#include <linux/pci.h>
55#include <linux/interrupt.h>
56#include <linux/delay.h>
57#include <linux/input.h>
58#include <linux/kfifo.h>
59#include <linux/workqueue.h>
60#include <linux/acpi.h>
34#include <acpi/acpi_drivers.h> 61#include <acpi/acpi_drivers.h>
35#include <acpi/acpi_bus.h> 62#include <acpi/acpi_bus.h>
36#include <asm/uaccess.h> 63#include <asm/uaccess.h>
64#include <linux/sonypi.h>
65#include <linux/sony-laptop.h>
66#ifdef CONFIG_SONY_LAPTOP_OLD
67#include <linux/poll.h>
68#include <linux/miscdevice.h>
69#endif
37 70
38#define ACPI_SNC_CLASS "sony" 71#define DRV_PFX "sony-laptop: "
39#define ACPI_SNC_HID "SNY5001" 72#define dprintk(msg...) do { \
40#define ACPI_SNC_DRIVER_NAME "ACPI Sony Notebook Control Driver v0.4" 73 if (debug) printk(KERN_WARNING DRV_PFX msg); \
74} while (0)
41 75
42/* the device uses 1-based values, while the backlight subsystem uses 76#define SONY_LAPTOP_DRIVER_VERSION "0.5"
43 0-based values */ 77
44#define SONY_MAX_BRIGHTNESS 8 78#define SONY_NC_CLASS "sony-nc"
79#define SONY_NC_HID "SNY5001"
80#define SONY_NC_DRIVER_NAME "Sony Notebook Control Driver"
45 81
46#define LOG_PFX KERN_WARNING "sony-laptop: " 82#define SONY_PIC_CLASS "sony-pic"
83#define SONY_PIC_HID "SNY6001"
84#define SONY_PIC_DRIVER_NAME "Sony Programmable IO Control Driver"
47 85
48MODULE_AUTHOR("Stelian Pop, Mattia Dongili"); 86MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
49MODULE_DESCRIPTION(ACPI_SNC_DRIVER_NAME); 87MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)");
50MODULE_LICENSE("GPL"); 88MODULE_LICENSE("GPL");
89MODULE_VERSION(SONY_LAPTOP_DRIVER_VERSION);
51 90
52static int debug; 91static int debug;
53module_param(debug, int, 0); 92module_param(debug, int, 0);
54MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help " 93MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
55 "the development of this driver"); 94 "the development of this driver");
56 95
57static ssize_t sony_acpi_show(struct device *, struct device_attribute *, 96static int no_spic; /* = 0 */
97module_param(no_spic, int, 0444);
98MODULE_PARM_DESC(no_spic,
99 "set this if you don't want to enable the SPIC device");
100
101static int compat; /* = 0 */
102module_param(compat, int, 0444);
103MODULE_PARM_DESC(compat,
104 "set this if you want to enable backward compatibility mode");
105
106static unsigned long mask = 0xffffffff;
107module_param(mask, ulong, 0644);
108MODULE_PARM_DESC(mask,
109 "set this to the mask of event you want to enable (see doc)");
110
111static int camera; /* = 0 */
112module_param(camera, int, 0444);
113MODULE_PARM_DESC(camera,
114 "set this to 1 to enable Motion Eye camera controls "
115 "(only use it if you have a C1VE or C1VN model)");
116
117#ifdef CONFIG_SONY_LAPTOP_OLD
118static int minor = -1;
119module_param(minor, int, 0);
120MODULE_PARM_DESC(minor,
121 "minor number of the misc device for the SPIC compatibility code, "
122 "default is -1 (automatic)");
123#endif
124
125/*********** Input Devices ***********/
126
127#define SONY_LAPTOP_BUF_SIZE 128
128struct sony_laptop_input_s {
129 atomic_t users;
130 struct input_dev *jog_dev;
131 struct input_dev *key_dev;
132 struct kfifo *fifo;
133 spinlock_t fifo_lock;
134 struct workqueue_struct *wq;
135};
136static struct sony_laptop_input_s sony_laptop_input = {
137 .users = ATOMIC_INIT(0),
138};
139
140struct sony_laptop_keypress {
141 struct input_dev *dev;
142 int key;
143};
144
145/* Correspondance table between sonypi events and input layer events */
146static struct {
147 int sonypiev;
148 int inputev;
149} sony_laptop_inputkeys[] = {
150 { SONYPI_EVENT_CAPTURE_PRESSED, KEY_CAMERA },
151 { SONYPI_EVENT_FNKEY_ONLY, KEY_FN },
152 { SONYPI_EVENT_FNKEY_ESC, KEY_FN_ESC },
153 { SONYPI_EVENT_FNKEY_F1, KEY_FN_F1 },
154 { SONYPI_EVENT_FNKEY_F2, KEY_FN_F2 },
155 { SONYPI_EVENT_FNKEY_F3, KEY_FN_F3 },
156 { SONYPI_EVENT_FNKEY_F4, KEY_FN_F4 },
157 { SONYPI_EVENT_FNKEY_F5, KEY_FN_F5 },
158 { SONYPI_EVENT_FNKEY_F6, KEY_FN_F6 },
159 { SONYPI_EVENT_FNKEY_F7, KEY_FN_F7 },
160 { SONYPI_EVENT_FNKEY_F8, KEY_FN_F8 },
161 { SONYPI_EVENT_FNKEY_F9, KEY_FN_F9 },
162 { SONYPI_EVENT_FNKEY_F10, KEY_FN_F10 },
163 { SONYPI_EVENT_FNKEY_F11, KEY_FN_F11 },
164 { SONYPI_EVENT_FNKEY_F12, KEY_FN_F12 },
165 { SONYPI_EVENT_FNKEY_1, KEY_FN_1 },
166 { SONYPI_EVENT_FNKEY_2, KEY_FN_2 },
167 { SONYPI_EVENT_FNKEY_D, KEY_FN_D },
168 { SONYPI_EVENT_FNKEY_E, KEY_FN_E },
169 { SONYPI_EVENT_FNKEY_F, KEY_FN_F },
170 { SONYPI_EVENT_FNKEY_S, KEY_FN_S },
171 { SONYPI_EVENT_FNKEY_B, KEY_FN_B },
172 { SONYPI_EVENT_BLUETOOTH_PRESSED, KEY_BLUE },
173 { SONYPI_EVENT_BLUETOOTH_ON, KEY_BLUE },
174 { SONYPI_EVENT_PKEY_P1, KEY_PROG1 },
175 { SONYPI_EVENT_PKEY_P2, KEY_PROG2 },
176 { SONYPI_EVENT_PKEY_P3, KEY_PROG3 },
177 { SONYPI_EVENT_BACK_PRESSED, KEY_BACK },
178 { SONYPI_EVENT_HELP_PRESSED, KEY_HELP },
179 { SONYPI_EVENT_ZOOM_PRESSED, KEY_ZOOM },
180 { SONYPI_EVENT_THUMBPHRASE_PRESSED, BTN_THUMB },
181 { 0, 0 },
182};
183
184/* release buttons after a short delay if pressed */
185static void do_sony_laptop_release_key(struct work_struct *work)
186{
187 struct sony_laptop_keypress kp;
188
189 while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp,
190 sizeof(kp)) == sizeof(kp)) {
191 msleep(10);
192 input_report_key(kp.dev, kp.key, 0);
193 input_sync(kp.dev);
194 }
195}
196static DECLARE_WORK(sony_laptop_release_key_work,
197 do_sony_laptop_release_key);
198
199/* forward event to the input subsytem */
200static void sony_laptop_report_input_event(u8 event)
201{
202 struct input_dev *jog_dev = sony_laptop_input.jog_dev;
203 struct input_dev *key_dev = sony_laptop_input.key_dev;
204 struct sony_laptop_keypress kp = { NULL };
205 int i;
206
207 if (event == SONYPI_EVENT_FNKEY_RELEASED) {
208 /* Nothing, not all VAIOs generate this event */
209 return;
210 }
211
212 /* report events */
213 switch (event) {
214 /* jog_dev events */
215 case SONYPI_EVENT_JOGDIAL_UP:
216 case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
217 input_report_rel(jog_dev, REL_WHEEL, 1);
218 input_sync(jog_dev);
219 return;
220
221 case SONYPI_EVENT_JOGDIAL_DOWN:
222 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
223 input_report_rel(jog_dev, REL_WHEEL, -1);
224 input_sync(jog_dev);
225 return;
226
227 /* key_dev events */
228 case SONYPI_EVENT_JOGDIAL_PRESSED:
229 kp.key = BTN_MIDDLE;
230 kp.dev = jog_dev;
231 break;
232
233 default:
234 for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++)
235 if (event == sony_laptop_inputkeys[i].sonypiev) {
236 kp.dev = key_dev;
237 kp.key = sony_laptop_inputkeys[i].inputev;
238 break;
239 }
240 break;
241 }
242
243 if (kp.dev) {
244 input_report_key(kp.dev, kp.key, 1);
245 input_sync(kp.dev);
246 kfifo_put(sony_laptop_input.fifo,
247 (unsigned char *)&kp, sizeof(kp));
248
249 if (!work_pending(&sony_laptop_release_key_work))
250 queue_work(sony_laptop_input.wq,
251 &sony_laptop_release_key_work);
252 } else
253 dprintk("unknown input event %.2x\n", event);
254}
255
256static int sony_laptop_setup_input(void)
257{
258 struct input_dev *jog_dev;
259 struct input_dev *key_dev;
260 int i;
261 int error;
262
263 /* don't run again if already initialized */
264 if (atomic_add_return(1, &sony_laptop_input.users) > 1)
265 return 0;
266
267 /* kfifo */
268 spin_lock_init(&sony_laptop_input.fifo_lock);
269 sony_laptop_input.fifo =
270 kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
271 &sony_laptop_input.fifo_lock);
272 if (IS_ERR(sony_laptop_input.fifo)) {
273 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
274 error = PTR_ERR(sony_laptop_input.fifo);
275 goto err_dec_users;
276 }
277
278 /* init workqueue */
279 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop");
280 if (!sony_laptop_input.wq) {
281 printk(KERN_ERR DRV_PFX
282 "Unabe to create workqueue.\n");
283 error = -ENXIO;
284 goto err_free_kfifo;
285 }
286
287 /* input keys */
288 key_dev = input_allocate_device();
289 if (!key_dev) {
290 error = -ENOMEM;
291 goto err_destroy_wq;
292 }
293
294 key_dev->name = "Sony Vaio Keys";
295 key_dev->id.bustype = BUS_ISA;
296 key_dev->id.vendor = PCI_VENDOR_ID_SONY;
297
298 /* Initialize the Input Drivers: special keys */
299 key_dev->evbit[0] = BIT(EV_KEY);
300 for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++)
301 if (sony_laptop_inputkeys[i].inputev)
302 set_bit(sony_laptop_inputkeys[i].inputev,
303 key_dev->keybit);
304
305 error = input_register_device(key_dev);
306 if (error)
307 goto err_free_keydev;
308
309 sony_laptop_input.key_dev = key_dev;
310
311 /* jogdial */
312 jog_dev = input_allocate_device();
313 if (!jog_dev) {
314 error = -ENOMEM;
315 goto err_unregister_keydev;
316 }
317
318 jog_dev->name = "Sony Vaio Jogdial";
319 jog_dev->id.bustype = BUS_ISA;
320 jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
321
322 jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
323 jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
324 jog_dev->relbit[0] = BIT(REL_WHEEL);
325
326 error = input_register_device(jog_dev);
327 if (error)
328 goto err_free_jogdev;
329
330 sony_laptop_input.jog_dev = jog_dev;
331
332 return 0;
333
334err_free_jogdev:
335 input_free_device(jog_dev);
336
337err_unregister_keydev:
338 input_unregister_device(key_dev);
339 /* to avoid kref underflow below at input_free_device */
340 key_dev = NULL;
341
342err_free_keydev:
343 input_free_device(key_dev);
344
345err_destroy_wq:
346 destroy_workqueue(sony_laptop_input.wq);
347
348err_free_kfifo:
349 kfifo_free(sony_laptop_input.fifo);
350
351err_dec_users:
352 atomic_dec(&sony_laptop_input.users);
353 return error;
354}
355
356static void sony_laptop_remove_input(void)
357{
358 /* cleanup only after the last user has gone */
359 if (!atomic_dec_and_test(&sony_laptop_input.users))
360 return;
361
362 /* flush workqueue first */
363 flush_workqueue(sony_laptop_input.wq);
364
365 /* destroy input devs */
366 input_unregister_device(sony_laptop_input.key_dev);
367 sony_laptop_input.key_dev = NULL;
368
369 if (sony_laptop_input.jog_dev) {
370 input_unregister_device(sony_laptop_input.jog_dev);
371 sony_laptop_input.jog_dev = NULL;
372 }
373
374 destroy_workqueue(sony_laptop_input.wq);
375 kfifo_free(sony_laptop_input.fifo);
376}
377
378/*********** Platform Device ***********/
379
380static atomic_t sony_pf_users = ATOMIC_INIT(0);
381static struct platform_driver sony_pf_driver = {
382 .driver = {
383 .name = "sony-laptop",
384 .owner = THIS_MODULE,
385 }
386};
387static struct platform_device *sony_pf_device;
388
389static int sony_pf_add(void)
390{
391 int ret = 0;
392
393 /* don't run again if already initialized */
394 if (atomic_add_return(1, &sony_pf_users) > 1)
395 return 0;
396
397 ret = platform_driver_register(&sony_pf_driver);
398 if (ret)
399 goto out;
400
401 sony_pf_device = platform_device_alloc("sony-laptop", -1);
402 if (!sony_pf_device) {
403 ret = -ENOMEM;
404 goto out_platform_registered;
405 }
406
407 ret = platform_device_add(sony_pf_device);
408 if (ret)
409 goto out_platform_alloced;
410
411 return 0;
412
413 out_platform_alloced:
414 platform_device_put(sony_pf_device);
415 sony_pf_device = NULL;
416 out_platform_registered:
417 platform_driver_unregister(&sony_pf_driver);
418 out:
419 atomic_dec(&sony_pf_users);
420 return ret;
421}
422
423static void sony_pf_remove(void)
424{
425 /* deregister only after the last user has gone */
426 if (!atomic_dec_and_test(&sony_pf_users))
427 return;
428
429 platform_device_del(sony_pf_device);
430 platform_device_put(sony_pf_device);
431 platform_driver_unregister(&sony_pf_driver);
432}
433
434/*********** SNC (SNY5001) Device ***********/
435
436/* the device uses 1-based values, while the backlight subsystem uses
437 0-based values */
438#define SONY_MAX_BRIGHTNESS 8
439
440#define SNC_VALIDATE_IN 0
441#define SNC_VALIDATE_OUT 1
442
443static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
58 char *); 444 char *);
59static ssize_t sony_acpi_store(struct device *, struct device_attribute *, 445static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
60 const char *, size_t); 446 const char *, size_t);
61static int boolean_validate(const int, const int); 447static int boolean_validate(const int, const int);
62static int brightness_default_validate(const int, const int); 448static int brightness_default_validate(const int, const int);
63 449
64#define SNC_VALIDATE_IN 0 450struct sony_nc_value {
65#define SNC_VALIDATE_OUT 1
66
67struct sony_acpi_value {
68 char *name; /* name of the entry */ 451 char *name; /* name of the entry */
69 char **acpiget; /* names of the ACPI get function */ 452 char **acpiget; /* names of the ACPI get function */
70 char **acpiset; /* names of the ACPI set function */ 453 char **acpiset; /* names of the ACPI set function */
@@ -75,65 +458,65 @@ struct sony_acpi_value {
75 struct device_attribute devattr; /* sysfs atribute */ 458 struct device_attribute devattr; /* sysfs atribute */
76}; 459};
77 460
78#define HANDLE_NAMES(_name, _values...) \ 461#define SNC_HANDLE_NAMES(_name, _values...) \
79 static char *snc_##_name[] = { _values, NULL } 462 static char *snc_##_name[] = { _values, NULL }
80 463
81#define SONY_ACPI_VALUE(_name, _getters, _setters, _validate, _debug) \ 464#define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \
82 { \ 465 { \
83 .name = __stringify(_name), \ 466 .name = __stringify(_name), \
84 .acpiget = _getters, \ 467 .acpiget = _getters, \
85 .acpiset = _setters, \ 468 .acpiset = _setters, \
86 .validate = _validate, \ 469 .validate = _validate, \
87 .debug = _debug, \ 470 .debug = _debug, \
88 .devattr = __ATTR(_name, 0, sony_acpi_show, sony_acpi_store), \ 471 .devattr = __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \
89 } 472 }
90 473
91#define SONY_ACPI_VALUE_NULL { .name = NULL } 474#define SNC_HANDLE_NULL { .name = NULL }
92 475
93HANDLE_NAMES(fnkey_get, "GHKE"); 476SNC_HANDLE_NAMES(fnkey_get, "GHKE");
94 477
95HANDLE_NAMES(brightness_def_get, "GPBR"); 478SNC_HANDLE_NAMES(brightness_def_get, "GPBR");
96HANDLE_NAMES(brightness_def_set, "SPBR"); 479SNC_HANDLE_NAMES(brightness_def_set, "SPBR");
97 480
98HANDLE_NAMES(cdpower_get, "GCDP"); 481SNC_HANDLE_NAMES(cdpower_get, "GCDP");
99HANDLE_NAMES(cdpower_set, "SCDP", "CDPW"); 482SNC_HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
100 483
101HANDLE_NAMES(audiopower_get, "GAZP"); 484SNC_HANDLE_NAMES(audiopower_get, "GAZP");
102HANDLE_NAMES(audiopower_set, "AZPW"); 485SNC_HANDLE_NAMES(audiopower_set, "AZPW");
103 486
104HANDLE_NAMES(lanpower_get, "GLNP"); 487SNC_HANDLE_NAMES(lanpower_get, "GLNP");
105HANDLE_NAMES(lanpower_set, "LNPW"); 488SNC_HANDLE_NAMES(lanpower_set, "LNPW");
106 489
107HANDLE_NAMES(PID_get, "GPID"); 490SNC_HANDLE_NAMES(PID_get, "GPID");
108 491
109HANDLE_NAMES(CTR_get, "GCTR"); 492SNC_HANDLE_NAMES(CTR_get, "GCTR");
110HANDLE_NAMES(CTR_set, "SCTR"); 493SNC_HANDLE_NAMES(CTR_set, "SCTR");
111 494
112HANDLE_NAMES(PCR_get, "GPCR"); 495SNC_HANDLE_NAMES(PCR_get, "GPCR");
113HANDLE_NAMES(PCR_set, "SPCR"); 496SNC_HANDLE_NAMES(PCR_set, "SPCR");
114 497
115HANDLE_NAMES(CMI_get, "GCMI"); 498SNC_HANDLE_NAMES(CMI_get, "GCMI");
116HANDLE_NAMES(CMI_set, "SCMI"); 499SNC_HANDLE_NAMES(CMI_set, "SCMI");
117 500
118static struct sony_acpi_value sony_acpi_values[] = { 501static struct sony_nc_value sony_nc_values[] = {
119 SONY_ACPI_VALUE(brightness_default, snc_brightness_def_get, 502 SNC_HANDLE(brightness_default, snc_brightness_def_get,
120 snc_brightness_def_set, brightness_default_validate, 0), 503 snc_brightness_def_set, brightness_default_validate, 0),
121 SONY_ACPI_VALUE(fnkey, snc_fnkey_get, NULL, NULL, 0), 504 SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
122 SONY_ACPI_VALUE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0), 505 SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
123 SONY_ACPI_VALUE(audiopower, snc_audiopower_get, snc_audiopower_set, 506 SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
124 boolean_validate, 0), 507 boolean_validate, 0),
125 SONY_ACPI_VALUE(lanpower, snc_lanpower_get, snc_lanpower_set, 508 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
126 boolean_validate, 1), 509 boolean_validate, 1),
127 /* unknown methods */ 510 /* unknown methods */
128 SONY_ACPI_VALUE(PID, snc_PID_get, NULL, NULL, 1), 511 SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1),
129 SONY_ACPI_VALUE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), 512 SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
130 SONY_ACPI_VALUE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1), 513 SNC_HANDLE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
131 SONY_ACPI_VALUE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1), 514 SNC_HANDLE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
132 SONY_ACPI_VALUE_NULL 515 SNC_HANDLE_NULL
133}; 516};
134 517
135static acpi_handle sony_acpi_handle; 518static acpi_handle sony_nc_acpi_handle;
136static struct acpi_device *sony_acpi_acpi_device = NULL; 519static struct acpi_device *sony_nc_acpi_device = NULL;
137 520
138/* 521/*
139 * acpi_evaluate_object wrappers 522 * acpi_evaluate_object wrappers
@@ -153,7 +536,7 @@ static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
153 return 0; 536 return 0;
154 } 537 }
155 538
156 printk(LOG_PFX "acpi_callreadfunc failed\n"); 539 printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n");
157 540
158 return -1; 541 return -1;
159} 542}
@@ -179,7 +562,7 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
179 if (status == AE_OK) { 562 if (status == AE_OK) {
180 if (result != NULL) { 563 if (result != NULL) {
181 if (out_obj.type != ACPI_TYPE_INTEGER) { 564 if (out_obj.type != ACPI_TYPE_INTEGER) {
182 printk(LOG_PFX "acpi_evaluate_object bad " 565 printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad "
183 "return type\n"); 566 "return type\n");
184 return -1; 567 return -1;
185 } 568 }
@@ -188,13 +571,13 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
188 return 0; 571 return 0;
189 } 572 }
190 573
191 printk(LOG_PFX "acpi_evaluate_object failed\n"); 574 printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n");
192 575
193 return -1; 576 return -1;
194} 577}
195 578
196/* 579/*
197 * sony_acpi_values input/output validate functions 580 * sony_nc_values input/output validate functions
198 */ 581 */
199 582
200/* brightness_default_validate: 583/* brightness_default_validate:
@@ -229,19 +612,19 @@ static int boolean_validate(const int direction, const int value)
229} 612}
230 613
231/* 614/*
232 * Sysfs show/store common to all sony_acpi_values 615 * Sysfs show/store common to all sony_nc_values
233 */ 616 */
234static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr, 617static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
235 char *buffer) 618 char *buffer)
236{ 619{
237 int value; 620 int value;
238 struct sony_acpi_value *item = 621 struct sony_nc_value *item =
239 container_of(attr, struct sony_acpi_value, devattr); 622 container_of(attr, struct sony_nc_value, devattr);
240 623
241 if (!*item->acpiget) 624 if (!*item->acpiget)
242 return -EIO; 625 return -EIO;
243 626
244 if (acpi_callgetfunc(sony_acpi_handle, *item->acpiget, &value) < 0) 627 if (acpi_callgetfunc(sony_nc_acpi_handle, *item->acpiget, &value) < 0)
245 return -EIO; 628 return -EIO;
246 629
247 if (item->validate) 630 if (item->validate)
@@ -250,13 +633,13 @@ static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr,
250 return snprintf(buffer, PAGE_SIZE, "%d\n", value); 633 return snprintf(buffer, PAGE_SIZE, "%d\n", value);
251} 634}
252 635
253static ssize_t sony_acpi_store(struct device *dev, 636static ssize_t sony_nc_sysfs_store(struct device *dev,
254 struct device_attribute *attr, 637 struct device_attribute *attr,
255 const char *buffer, size_t count) 638 const char *buffer, size_t count)
256{ 639{
257 int value; 640 int value;
258 struct sony_acpi_value *item = 641 struct sony_nc_value *item =
259 container_of(attr, struct sony_acpi_value, devattr); 642 container_of(attr, struct sony_nc_value, devattr);
260 643
261 if (!item->acpiset) 644 if (!item->acpiset)
262 return -EIO; 645 return -EIO;
@@ -272,118 +655,20 @@ static ssize_t sony_acpi_store(struct device *dev,
272 if (value < 0) 655 if (value < 0)
273 return value; 656 return value;
274 657
275 if (acpi_callsetfunc(sony_acpi_handle, *item->acpiset, value, NULL) < 0) 658 if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0)
276 return -EIO; 659 return -EIO;
277 item->value = value; 660 item->value = value;
278 item->valid = 1; 661 item->valid = 1;
279 return count; 662 return count;
280} 663}
281 664
282/*
283 * Platform device
284 */
285static struct platform_driver sncpf_driver = {
286 .driver = {
287 .name = "sony-laptop",
288 .owner = THIS_MODULE,
289 }
290};
291static struct platform_device *sncpf_device;
292
293static int sony_snc_pf_add(void)
294{
295 acpi_handle handle;
296 struct sony_acpi_value *item;
297 int ret = 0;
298
299 ret = platform_driver_register(&sncpf_driver);
300 if (ret)
301 goto out;
302
303 sncpf_device = platform_device_alloc("sony-laptop", -1);
304 if (!sncpf_device) {
305 ret = -ENOMEM;
306 goto out_platform_registered;
307 }
308
309 ret = platform_device_add(sncpf_device);
310 if (ret)
311 goto out_platform_alloced;
312
313 for (item = sony_acpi_values; item->name; ++item) {
314
315 if (!debug && item->debug)
316 continue;
317
318 /* find the available acpiget as described in the DSDT */
319 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
320 if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
321 *item->acpiget,
322 &handle))) {
323 if (debug)
324 printk(LOG_PFX "Found %s getter: %s\n",
325 item->name, *item->acpiget);
326 item->devattr.attr.mode |= S_IRUGO;
327 break;
328 }
329 }
330
331 /* find the available acpiset as described in the DSDT */
332 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
333 if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
334 *item->acpiset,
335 &handle))) {
336 if (debug)
337 printk(LOG_PFX "Found %s setter: %s\n",
338 item->name, *item->acpiset);
339 item->devattr.attr.mode |= S_IWUSR;
340 break;
341 }
342 }
343
344 if (item->devattr.attr.mode != 0) {
345 ret =
346 device_create_file(&sncpf_device->dev,
347 &item->devattr);
348 if (ret)
349 goto out_sysfs;
350 }
351 }
352
353 return 0;
354
355 out_sysfs:
356 for (item = sony_acpi_values; item->name; ++item) {
357 device_remove_file(&sncpf_device->dev, &item->devattr);
358 }
359 platform_device_del(sncpf_device);
360 out_platform_alloced:
361 platform_device_put(sncpf_device);
362 out_platform_registered:
363 platform_driver_unregister(&sncpf_driver);
364 out:
365 return ret;
366}
367
368static void sony_snc_pf_remove(void)
369{
370 struct sony_acpi_value *item;
371
372 for (item = sony_acpi_values; item->name; ++item) {
373 device_remove_file(&sncpf_device->dev, &item->devattr);
374 }
375
376 platform_device_del(sncpf_device);
377 platform_device_put(sncpf_device);
378 platform_driver_unregister(&sncpf_driver);
379}
380 665
381/* 666/*
382 * Backlight device 667 * Backlight device
383 */ 668 */
384static int sony_backlight_update_status(struct backlight_device *bd) 669static int sony_backlight_update_status(struct backlight_device *bd)
385{ 670{
386 return acpi_callsetfunc(sony_acpi_handle, "SBRT", 671 return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
387 bd->props.brightness + 1, NULL); 672 bd->props.brightness + 1, NULL);
388} 673}
389 674
@@ -391,7 +676,7 @@ static int sony_backlight_get_brightness(struct backlight_device *bd)
391{ 676{
392 int value; 677 int value;
393 678
394 if (acpi_callgetfunc(sony_acpi_handle, "GBRT", &value)) 679 if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value))
395 return 0; 680 return 0;
396 /* brightness levels are 1-based, while backlight ones are 0-based */ 681 /* brightness levels are 1-based, while backlight ones are 0-based */
397 return value - 1; 682 return value - 1;
@@ -408,9 +693,9 @@ static struct backlight_ops sony_backlight_ops = {
408 */ 693 */
409static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) 694static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
410{ 695{
411 if (debug) 696 dprintk("sony_acpi_notify, event: %d\n", event);
412 printk(LOG_PFX "sony_acpi_notify, event: %d\n", event); 697 sony_laptop_report_input_event(event);
413 acpi_bus_generate_event(sony_acpi_acpi_device, 1, event); 698 acpi_bus_generate_event(sony_nc_acpi_device, 1, event);
414} 699}
415 700
416static acpi_status sony_walk_callback(acpi_handle handle, u32 level, 701static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
@@ -422,7 +707,7 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
422 node = (struct acpi_namespace_node *)handle; 707 node = (struct acpi_namespace_node *)handle;
423 operand = (union acpi_operand_object *)node->object; 708 operand = (union acpi_operand_object *)node->object;
424 709
425 printk(LOG_PFX "method: name: %4.4s, args %X\n", node->name.ascii, 710 printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", node->name.ascii,
426 (u32) operand->method.param_count); 711 (u32) operand->method.param_count);
427 712
428 return AE_OK; 713 return AE_OK;
@@ -431,16 +716,16 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
431/* 716/*
432 * ACPI device 717 * ACPI device
433 */ 718 */
434static int sony_acpi_resume(struct acpi_device *device) 719static int sony_nc_resume(struct acpi_device *device)
435{ 720{
436 struct sony_acpi_value *item; 721 struct sony_nc_value *item;
437 722
438 for (item = sony_acpi_values; item->name; item++) { 723 for (item = sony_nc_values; item->name; item++) {
439 int ret; 724 int ret;
440 725
441 if (!item->valid) 726 if (!item->valid)
442 continue; 727 continue;
443 ret = acpi_callsetfunc(sony_acpi_handle, *item->acpiset, 728 ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
444 item->value, NULL); 729 item->value, NULL);
445 if (ret < 0) { 730 if (ret < 0) {
446 printk("%s: %d\n", __FUNCTION__, ret); 731 printk("%s: %d\n", __FUNCTION__, ret);
@@ -450,42 +735,55 @@ static int sony_acpi_resume(struct acpi_device *device)
450 return 0; 735 return 0;
451} 736}
452 737
453static int sony_acpi_add(struct acpi_device *device) 738static int sony_nc_add(struct acpi_device *device)
454{ 739{
455 acpi_status status; 740 acpi_status status;
456 int result = 0; 741 int result = 0;
457 acpi_handle handle; 742 acpi_handle handle;
743 struct sony_nc_value *item;
744
745 printk(KERN_INFO DRV_PFX "%s v%s.\n",
746 SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
458 747
459 sony_acpi_acpi_device = device; 748 sony_nc_acpi_device = device;
749 strcpy(acpi_device_class(device), "sony/hotkey");
460 750
461 sony_acpi_handle = device->handle; 751 sony_nc_acpi_handle = device->handle;
462 752
463 if (debug) { 753 if (debug) {
464 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_acpi_handle, 754 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
465 1, sony_walk_callback, NULL, NULL); 755 1, sony_walk_callback, NULL, NULL);
466 if (ACPI_FAILURE(status)) { 756 if (ACPI_FAILURE(status)) {
467 printk(LOG_PFX "unable to walk acpi resources\n"); 757 printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
468 result = -ENODEV; 758 result = -ENODEV;
469 goto outwalk; 759 goto outwalk;
470 } 760 }
471 } 761 }
472 762
473 status = acpi_install_notify_handler(sony_acpi_handle, 763 /* setup input devices and helper fifo */
764 result = sony_laptop_setup_input();
765 if (result) {
766 printk(KERN_ERR DRV_PFX
767 "Unabe to create input devices.\n");
768 goto outwalk;
769 }
770
771 status = acpi_install_notify_handler(sony_nc_acpi_handle,
474 ACPI_DEVICE_NOTIFY, 772 ACPI_DEVICE_NOTIFY,
475 sony_acpi_notify, NULL); 773 sony_acpi_notify, NULL);
476 if (ACPI_FAILURE(status)) { 774 if (ACPI_FAILURE(status)) {
477 printk(LOG_PFX "unable to install notify handler\n"); 775 printk(KERN_WARNING DRV_PFX "unable to install notify handler\n");
478 result = -ENODEV; 776 result = -ENODEV;
479 goto outwalk; 777 goto outinput;
480 } 778 }
481 779
482 if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, "GBRT", &handle))) { 780 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) {
483 sony_backlight_device = backlight_device_register("sony", NULL, 781 sony_backlight_device = backlight_device_register("sony", NULL,
484 NULL, 782 NULL,
485 &sony_backlight_ops); 783 &sony_backlight_ops);
486 784
487 if (IS_ERR(sony_backlight_device)) { 785 if (IS_ERR(sony_backlight_device)) {
488 printk(LOG_PFX "unable to register backlight device\n"); 786 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
489 sony_backlight_device = NULL; 787 sony_backlight_device = NULL;
490 } else { 788 } else {
491 sony_backlight_device->props.brightness = 789 sony_backlight_device->props.brightness =
@@ -497,68 +795,1497 @@ static int sony_acpi_add(struct acpi_device *device)
497 795
498 } 796 }
499 797
500 if (sony_snc_pf_add()) 798 result = sony_pf_add();
799 if (result)
501 goto outbacklight; 800 goto outbacklight;
502 801
503 printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully installed\n"); 802 /* create sony_pf sysfs attributes related to the SNC device */
803 for (item = sony_nc_values; item->name; ++item) {
804
805 if (!debug && item->debug)
806 continue;
807
808 /* find the available acpiget as described in the DSDT */
809 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
810 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
811 *item->acpiget,
812 &handle))) {
813 dprintk("Found %s getter: %s\n",
814 item->name, *item->acpiget);
815 item->devattr.attr.mode |= S_IRUGO;
816 break;
817 }
818 }
819
820 /* find the available acpiset as described in the DSDT */
821 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
822 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
823 *item->acpiset,
824 &handle))) {
825 dprintk("Found %s setter: %s\n",
826 item->name, *item->acpiset);
827 item->devattr.attr.mode |= S_IWUSR;
828 break;
829 }
830 }
831
832 if (item->devattr.attr.mode != 0) {
833 result =
834 device_create_file(&sony_pf_device->dev,
835 &item->devattr);
836 if (result)
837 goto out_sysfs;
838 }
839 }
504 840
505 return 0; 841 return 0;
506 842
843 out_sysfs:
844 for (item = sony_nc_values; item->name; ++item) {
845 device_remove_file(&sony_pf_device->dev, &item->devattr);
846 }
847 sony_pf_remove();
848
507 outbacklight: 849 outbacklight:
508 if (sony_backlight_device) 850 if (sony_backlight_device)
509 backlight_device_unregister(sony_backlight_device); 851 backlight_device_unregister(sony_backlight_device);
510 852
511 status = acpi_remove_notify_handler(sony_acpi_handle, 853 status = acpi_remove_notify_handler(sony_nc_acpi_handle,
512 ACPI_DEVICE_NOTIFY, 854 ACPI_DEVICE_NOTIFY,
513 sony_acpi_notify); 855 sony_acpi_notify);
514 if (ACPI_FAILURE(status)) 856 if (ACPI_FAILURE(status))
515 printk(LOG_PFX "unable to remove notify handler\n"); 857 printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n");
858
859 outinput:
860 sony_laptop_remove_input();
861
516 outwalk: 862 outwalk:
517 return result; 863 return result;
518} 864}
519 865
520static int sony_acpi_remove(struct acpi_device *device, int type) 866static int sony_nc_remove(struct acpi_device *device, int type)
521{ 867{
522 acpi_status status; 868 acpi_status status;
869 struct sony_nc_value *item;
523 870
524 if (sony_backlight_device) 871 if (sony_backlight_device)
525 backlight_device_unregister(sony_backlight_device); 872 backlight_device_unregister(sony_backlight_device);
526 873
527 sony_acpi_acpi_device = NULL; 874 sony_nc_acpi_device = NULL;
528 875
529 status = acpi_remove_notify_handler(sony_acpi_handle, 876 status = acpi_remove_notify_handler(sony_nc_acpi_handle,
530 ACPI_DEVICE_NOTIFY, 877 ACPI_DEVICE_NOTIFY,
531 sony_acpi_notify); 878 sony_acpi_notify);
532 if (ACPI_FAILURE(status)) 879 if (ACPI_FAILURE(status))
533 printk(LOG_PFX "unable to remove notify handler\n"); 880 printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n");
534 881
535 sony_snc_pf_remove(); 882 for (item = sony_nc_values; item->name; ++item) {
883 device_remove_file(&sony_pf_device->dev, &item->devattr);
884 }
536 885
537 printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully removed\n"); 886 sony_pf_remove();
887 sony_laptop_remove_input();
888 dprintk(SONY_NC_DRIVER_NAME " removed.\n");
538 889
539 return 0; 890 return 0;
540} 891}
541 892
542static struct acpi_driver sony_acpi_driver = { 893static struct acpi_driver sony_nc_driver = {
543 .name = ACPI_SNC_DRIVER_NAME, 894 .name = SONY_NC_DRIVER_NAME,
544 .class = ACPI_SNC_CLASS, 895 .class = SONY_NC_CLASS,
545 .ids = ACPI_SNC_HID, 896 .ids = SONY_NC_HID,
897 .owner = THIS_MODULE,
546 .ops = { 898 .ops = {
547 .add = sony_acpi_add, 899 .add = sony_nc_add,
548 .remove = sony_acpi_remove, 900 .remove = sony_nc_remove,
549 .resume = sony_acpi_resume, 901 .resume = sony_nc_resume,
550 }, 902 },
551}; 903};
552 904
553static int __init sony_acpi_init(void) 905/*********** SPIC (SNY6001) Device ***********/
906
907#define SONYPI_DEVICE_TYPE1 0x00000001
908#define SONYPI_DEVICE_TYPE2 0x00000002
909#define SONYPI_DEVICE_TYPE3 0x00000004
910
911#define SONY_PIC_EV_MASK 0xff
912
913struct sony_pic_ioport {
914 struct acpi_resource_io io;
915 struct list_head list;
916};
917
918struct sony_pic_irq {
919 struct acpi_resource_irq irq;
920 struct list_head list;
921};
922
923struct sony_pic_dev {
924 int model;
925 u8 camera_power;
926 u8 bluetooth_power;
927 u8 wwan_power;
928 struct acpi_device *acpi_dev;
929 struct sony_pic_irq *cur_irq;
930 struct sony_pic_ioport *cur_ioport;
931 struct list_head interrupts;
932 struct list_head ioports;
933 struct mutex lock;
934};
935
936static struct sony_pic_dev spic_dev = {
937 .interrupts = LIST_HEAD_INIT(spic_dev.interrupts),
938 .ioports = LIST_HEAD_INIT(spic_dev.ioports),
939};
940
941/* Event masks */
942#define SONYPI_JOGGER_MASK 0x00000001
943#define SONYPI_CAPTURE_MASK 0x00000002
944#define SONYPI_FNKEY_MASK 0x00000004
945#define SONYPI_BLUETOOTH_MASK 0x00000008
946#define SONYPI_PKEY_MASK 0x00000010
947#define SONYPI_BACK_MASK 0x00000020
948#define SONYPI_HELP_MASK 0x00000040
949#define SONYPI_LID_MASK 0x00000080
950#define SONYPI_ZOOM_MASK 0x00000100
951#define SONYPI_THUMBPHRASE_MASK 0x00000200
952#define SONYPI_MEYE_MASK 0x00000400
953#define SONYPI_MEMORYSTICK_MASK 0x00000800
954#define SONYPI_BATTERY_MASK 0x00001000
955#define SONYPI_WIRELESS_MASK 0x00002000
956
957struct sonypi_event {
958 u8 data;
959 u8 event;
960};
961
962/* The set of possible button release events */
963static struct sonypi_event sonypi_releaseev[] = {
964 { 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED },
965 { 0, 0 }
966};
967
968/* The set of possible jogger events */
969static struct sonypi_event sonypi_joggerev[] = {
970 { 0x1f, SONYPI_EVENT_JOGDIAL_UP },
971 { 0x01, SONYPI_EVENT_JOGDIAL_DOWN },
972 { 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED },
973 { 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED },
974 { 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP },
975 { 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN },
976 { 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED },
977 { 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED },
978 { 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP },
979 { 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN },
980 { 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED },
981 { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED },
982 { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED },
983 { 0, 0 }
984};
985
986/* The set of possible capture button events */
987static struct sonypi_event sonypi_captureev[] = {
988 { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
989 { 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
990 { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
991 { 0, 0 }
992};
993
994/* The set of possible fnkeys events */
995static struct sonypi_event sonypi_fnkeyev[] = {
996 { 0x10, SONYPI_EVENT_FNKEY_ESC },
997 { 0x11, SONYPI_EVENT_FNKEY_F1 },
998 { 0x12, SONYPI_EVENT_FNKEY_F2 },
999 { 0x13, SONYPI_EVENT_FNKEY_F3 },
1000 { 0x14, SONYPI_EVENT_FNKEY_F4 },
1001 { 0x15, SONYPI_EVENT_FNKEY_F5 },
1002 { 0x16, SONYPI_EVENT_FNKEY_F6 },
1003 { 0x17, SONYPI_EVENT_FNKEY_F7 },
1004 { 0x18, SONYPI_EVENT_FNKEY_F8 },
1005 { 0x19, SONYPI_EVENT_FNKEY_F9 },
1006 { 0x1a, SONYPI_EVENT_FNKEY_F10 },
1007 { 0x1b, SONYPI_EVENT_FNKEY_F11 },
1008 { 0x1c, SONYPI_EVENT_FNKEY_F12 },
1009 { 0x1f, SONYPI_EVENT_FNKEY_RELEASED },
1010 { 0x21, SONYPI_EVENT_FNKEY_1 },
1011 { 0x22, SONYPI_EVENT_FNKEY_2 },
1012 { 0x31, SONYPI_EVENT_FNKEY_D },
1013 { 0x32, SONYPI_EVENT_FNKEY_E },
1014 { 0x33, SONYPI_EVENT_FNKEY_F },
1015 { 0x34, SONYPI_EVENT_FNKEY_S },
1016 { 0x35, SONYPI_EVENT_FNKEY_B },
1017 { 0x36, SONYPI_EVENT_FNKEY_ONLY },
1018 { 0, 0 }
1019};
1020
1021/* The set of possible program key events */
1022static struct sonypi_event sonypi_pkeyev[] = {
1023 { 0x01, SONYPI_EVENT_PKEY_P1 },
1024 { 0x02, SONYPI_EVENT_PKEY_P2 },
1025 { 0x04, SONYPI_EVENT_PKEY_P3 },
1026 { 0x5c, SONYPI_EVENT_PKEY_P1 },
1027 { 0, 0 }
1028};
1029
1030/* The set of possible bluetooth events */
1031static struct sonypi_event sonypi_blueev[] = {
1032 { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
1033 { 0x59, SONYPI_EVENT_BLUETOOTH_ON },
1034 { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
1035 { 0, 0 }
1036};
1037
1038/* The set of possible wireless events */
1039static struct sonypi_event sonypi_wlessev[] = {
1040 { 0x59, SONYPI_EVENT_WIRELESS_ON },
1041 { 0x5a, SONYPI_EVENT_WIRELESS_OFF },
1042 { 0, 0 }
1043};
1044
1045/* The set of possible back button events */
1046static struct sonypi_event sonypi_backev[] = {
1047 { 0x20, SONYPI_EVENT_BACK_PRESSED },
1048 { 0, 0 }
1049};
1050
1051/* The set of possible help button events */
1052static struct sonypi_event sonypi_helpev[] = {
1053 { 0x3b, SONYPI_EVENT_HELP_PRESSED },
1054 { 0, 0 }
1055};
1056
1057
1058/* The set of possible lid events */
1059static struct sonypi_event sonypi_lidev[] = {
1060 { 0x51, SONYPI_EVENT_LID_CLOSED },
1061 { 0x50, SONYPI_EVENT_LID_OPENED },
1062 { 0, 0 }
1063};
1064
1065/* The set of possible zoom events */
1066static struct sonypi_event sonypi_zoomev[] = {
1067 { 0x39, SONYPI_EVENT_ZOOM_PRESSED },
1068 { 0, 0 }
1069};
1070
1071/* The set of possible thumbphrase events */
1072static struct sonypi_event sonypi_thumbphraseev[] = {
1073 { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED },
1074 { 0, 0 }
1075};
1076
1077/* The set of possible motioneye camera events */
1078static struct sonypi_event sonypi_meyeev[] = {
1079 { 0x00, SONYPI_EVENT_MEYE_FACE },
1080 { 0x01, SONYPI_EVENT_MEYE_OPPOSITE },
1081 { 0, 0 }
1082};
1083
1084/* The set of possible memorystick events */
1085static struct sonypi_event sonypi_memorystickev[] = {
1086 { 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT },
1087 { 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT },
1088 { 0, 0 }
1089};
1090
1091/* The set of possible battery events */
1092static struct sonypi_event sonypi_batteryev[] = {
1093 { 0x20, SONYPI_EVENT_BATTERY_INSERT },
1094 { 0x30, SONYPI_EVENT_BATTERY_REMOVE },
1095 { 0, 0 }
1096};
1097
1098static struct sonypi_eventtypes {
1099 int model;
1100 u8 data;
1101 unsigned long mask;
1102 struct sonypi_event * events;
1103} sony_pic_eventtypes[] = {
1104 { SONYPI_DEVICE_TYPE1, 0, 0xffffffff, sonypi_releaseev },
1105 { SONYPI_DEVICE_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
1106 { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev },
1107 { SONYPI_DEVICE_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
1108 { SONYPI_DEVICE_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
1109 { SONYPI_DEVICE_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
1110 { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
1111 { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
1112 { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
1113 { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
1114
1115 { SONYPI_DEVICE_TYPE2, 0, 0xffffffff, sonypi_releaseev },
1116 { SONYPI_DEVICE_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev },
1117 { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
1118 { SONYPI_DEVICE_TYPE2, 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
1119 { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
1120 { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
1121 { SONYPI_DEVICE_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
1122 { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev },
1123 { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev },
1124 { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
1125 { SONYPI_DEVICE_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
1126 { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
1127 { SONYPI_DEVICE_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
1128 { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
1129
1130 { SONYPI_DEVICE_TYPE3, 0, 0xffffffff, sonypi_releaseev },
1131 { SONYPI_DEVICE_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
1132 { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
1133 { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
1134 { SONYPI_DEVICE_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
1135 { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
1136 { 0 }
1137};
1138
1139static int sony_pic_detect_device_type(void)
1140{
1141 struct pci_dev *pcidev;
1142 int model = 0;
1143
1144 if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1145 PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
1146 model = SONYPI_DEVICE_TYPE1;
1147
1148 else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1149 PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
1150 model = SONYPI_DEVICE_TYPE3;
1151
1152 else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1153 PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
1154 model = SONYPI_DEVICE_TYPE3;
1155
1156 else
1157 model = SONYPI_DEVICE_TYPE2;
1158
1159 if (pcidev)
1160 pci_dev_put(pcidev);
1161
1162 printk(KERN_INFO DRV_PFX "detected Type%d model\n",
1163 model == SONYPI_DEVICE_TYPE1 ? 1 :
1164 model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
1165 return model;
1166}
1167
1168#define ITERATIONS_LONG 10000
1169#define ITERATIONS_SHORT 10
1170#define wait_on_command(command, iterations) { \
1171 unsigned int n = iterations; \
1172 while (--n && (command)) \
1173 udelay(1); \
1174 if (!n) \
1175 dprintk("command failed at %s : %s (line %d)\n", \
1176 __FILE__, __FUNCTION__, __LINE__); \
1177}
1178
1179static u8 sony_pic_call1(u8 dev)
1180{
1181 u8 v1, v2;
1182
1183 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
1184 ITERATIONS_LONG);
1185 outb(dev, spic_dev.cur_ioport->io.minimum + 4);
1186 v1 = inb_p(spic_dev.cur_ioport->io.minimum + 4);
1187 v2 = inb_p(spic_dev.cur_ioport->io.minimum);
1188 dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1);
1189 return v2;
1190}
1191
1192static u8 sony_pic_call2(u8 dev, u8 fn)
1193{
1194 u8 v1;
1195
1196 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
1197 ITERATIONS_LONG);
1198 outb(dev, spic_dev.cur_ioport->io.minimum + 4);
1199 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
1200 ITERATIONS_LONG);
1201 outb(fn, spic_dev.cur_ioport->io.minimum);
1202 v1 = inb_p(spic_dev.cur_ioport->io.minimum);
1203 dprintk("sony_pic_call2: 0x%.4x\n", v1);
1204 return v1;
1205}
1206
1207static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
1208{
1209 u8 v1;
1210
1211 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
1212 outb(dev, spic_dev.cur_ioport->io.minimum + 4);
1213 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
1214 outb(fn, spic_dev.cur_ioport->io.minimum);
1215 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
1216 outb(v, spic_dev.cur_ioport->io.minimum);
1217 v1 = inb_p(spic_dev.cur_ioport->io.minimum);
1218 dprintk("sony_pic_call3: 0x%.4x\n", v1);
1219 return v1;
1220}
1221
1222/* camera tests and poweron/poweroff */
1223#define SONYPI_CAMERA_PICTURE 5
1224#define SONYPI_CAMERA_CONTROL 0x10
1225
1226#define SONYPI_CAMERA_BRIGHTNESS 0
1227#define SONYPI_CAMERA_CONTRAST 1
1228#define SONYPI_CAMERA_HUE 2
1229#define SONYPI_CAMERA_COLOR 3
1230#define SONYPI_CAMERA_SHARPNESS 4
1231
1232#define SONYPI_CAMERA_EXPOSURE_MASK 0xC
1233#define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3
1234#define SONYPI_CAMERA_PICTURE_MODE_MASK 0x30
1235#define SONYPI_CAMERA_MUTE_MASK 0x40
1236
1237/* the rest don't need a loop until not 0xff */
1238#define SONYPI_CAMERA_AGC 6
1239#define SONYPI_CAMERA_AGC_MASK 0x30
1240#define SONYPI_CAMERA_SHUTTER_MASK 0x7
1241
1242#define SONYPI_CAMERA_SHUTDOWN_REQUEST 7
1243#define SONYPI_CAMERA_CONTROL 0x10
1244
1245#define SONYPI_CAMERA_STATUS 7
1246#define SONYPI_CAMERA_STATUS_READY 0x2
1247#define SONYPI_CAMERA_STATUS_POSITION 0x4
1248
1249#define SONYPI_DIRECTION_BACKWARDS 0x4
1250
1251#define SONYPI_CAMERA_REVISION 8
1252#define SONYPI_CAMERA_ROMVERSION 9
1253
1254static int __sony_pic_camera_ready(void)
1255{
1256 u8 v;
1257
1258 v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
1259 return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
1260}
1261
1262static int __sony_pic_camera_off(void)
1263{
1264 if (!camera) {
1265 printk(KERN_WARNING DRV_PFX "camera control not enabled\n");
1266 return -ENODEV;
1267 }
1268
1269 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
1270 SONYPI_CAMERA_MUTE_MASK),
1271 ITERATIONS_SHORT);
1272
1273 if (spic_dev.camera_power) {
1274 sony_pic_call2(0x91, 0);
1275 spic_dev.camera_power = 0;
1276 }
1277 return 0;
1278}
1279
1280static int __sony_pic_camera_on(void)
554{ 1281{
555 return acpi_bus_register_driver(&sony_acpi_driver); 1282 int i, j, x;
1283
1284 if (!camera) {
1285 printk(KERN_WARNING DRV_PFX "camera control not enabled\n");
1286 return -ENODEV;
1287 }
1288
1289 if (spic_dev.camera_power)
1290 return 0;
1291
1292 for (j = 5; j > 0; j--) {
1293
1294 for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
1295 msleep(10);
1296 sony_pic_call1(0x93);
1297
1298 for (i = 400; i > 0; i--) {
1299 if (__sony_pic_camera_ready())
1300 break;
1301 msleep(10);
1302 }
1303 if (i)
1304 break;
1305 }
1306
1307 if (j == 0) {
1308 printk(KERN_WARNING DRV_PFX "failed to power on camera\n");
1309 return -ENODEV;
1310 }
1311
1312 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL,
1313 0x5a),
1314 ITERATIONS_SHORT);
1315
1316 spic_dev.camera_power = 1;
1317 return 0;
1318}
1319
1320/* External camera command (exported to the motion eye v4l driver) */
1321int sony_pic_camera_command(int command, u8 value)
1322{
1323 if (!camera)
1324 return -EIO;
1325
1326 mutex_lock(&spic_dev.lock);
1327
1328 switch (command) {
1329 case SONY_PIC_COMMAND_SETCAMERA:
1330 if (value)
1331 __sony_pic_camera_on();
1332 else
1333 __sony_pic_camera_off();
1334 break;
1335 case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
1336 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value),
1337 ITERATIONS_SHORT);
1338 break;
1339 case SONY_PIC_COMMAND_SETCAMERACONTRAST:
1340 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
1341 ITERATIONS_SHORT);
1342 break;
1343 case SONY_PIC_COMMAND_SETCAMERAHUE:
1344 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
1345 ITERATIONS_SHORT);
1346 break;
1347 case SONY_PIC_COMMAND_SETCAMERACOLOR:
1348 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
1349 ITERATIONS_SHORT);
1350 break;
1351 case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
1352 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
1353 ITERATIONS_SHORT);
1354 break;
1355 case SONY_PIC_COMMAND_SETCAMERAPICTURE:
1356 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
1357 ITERATIONS_SHORT);
1358 break;
1359 case SONY_PIC_COMMAND_SETCAMERAAGC:
1360 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
1361 ITERATIONS_SHORT);
1362 break;
1363 default:
1364 printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n",
1365 command);
1366 break;
1367 }
1368 mutex_unlock(&spic_dev.lock);
1369 return 0;
1370}
1371EXPORT_SYMBOL(sony_pic_camera_command);
1372
1373/* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */
1374static void sony_pic_set_wwanpower(u8 state)
1375{
1376 state = !!state;
1377 mutex_lock(&spic_dev.lock);
1378 if (spic_dev.wwan_power == state) {
1379 mutex_unlock(&spic_dev.lock);
1380 return;
1381 }
1382 sony_pic_call2(0xB0, state);
1383 spic_dev.wwan_power = state;
1384 mutex_unlock(&spic_dev.lock);
1385}
1386
1387static ssize_t sony_pic_wwanpower_store(struct device *dev,
1388 struct device_attribute *attr,
1389 const char *buffer, size_t count)
1390{
1391 unsigned long value;
1392 if (count > 31)
1393 return -EINVAL;
1394
1395 value = simple_strtoul(buffer, NULL, 10);
1396 sony_pic_set_wwanpower(value);
1397
1398 return count;
1399}
1400
1401static ssize_t sony_pic_wwanpower_show(struct device *dev,
1402 struct device_attribute *attr, char *buffer)
1403{
1404 ssize_t count;
1405 mutex_lock(&spic_dev.lock);
1406 count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.wwan_power);
1407 mutex_unlock(&spic_dev.lock);
1408 return count;
1409}
1410
1411/* bluetooth subsystem power state */
1412static void __sony_pic_set_bluetoothpower(u8 state)
1413{
1414 state = !!state;
1415 if (spic_dev.bluetooth_power == state)
1416 return;
1417 sony_pic_call2(0x96, state);
1418 sony_pic_call1(0x82);
1419 spic_dev.bluetooth_power = state;
1420}
1421
1422static ssize_t sony_pic_bluetoothpower_store(struct device *dev,
1423 struct device_attribute *attr,
1424 const char *buffer, size_t count)
1425{
1426 unsigned long value;
1427 if (count > 31)
1428 return -EINVAL;
1429
1430 value = simple_strtoul(buffer, NULL, 10);
1431 mutex_lock(&spic_dev.lock);
1432 __sony_pic_set_bluetoothpower(value);
1433 mutex_unlock(&spic_dev.lock);
1434
1435 return count;
1436}
1437
1438static ssize_t sony_pic_bluetoothpower_show(struct device *dev,
1439 struct device_attribute *attr, char *buffer)
1440{
1441 ssize_t count = 0;
1442 mutex_lock(&spic_dev.lock);
1443 count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power);
1444 mutex_unlock(&spic_dev.lock);
1445 return count;
1446}
1447
1448/* fan speed */
1449/* FAN0 information (reverse engineered from ACPI tables) */
1450#define SONY_PIC_FAN0_STATUS 0x93
1451static int sony_pic_set_fanspeed(unsigned long value)
1452{
1453 return ec_write(SONY_PIC_FAN0_STATUS, value);
1454}
1455
1456static int sony_pic_get_fanspeed(u8 *value)
1457{
1458 return ec_read(SONY_PIC_FAN0_STATUS, value);
1459}
1460
1461static ssize_t sony_pic_fanspeed_store(struct device *dev,
1462 struct device_attribute *attr,
1463 const char *buffer, size_t count)
1464{
1465 unsigned long value;
1466 if (count > 31)
1467 return -EINVAL;
1468
1469 value = simple_strtoul(buffer, NULL, 10);
1470 if (sony_pic_set_fanspeed(value))
1471 return -EIO;
1472
1473 return count;
1474}
1475
1476static ssize_t sony_pic_fanspeed_show(struct device *dev,
1477 struct device_attribute *attr, char *buffer)
1478{
1479 u8 value = 0;
1480 if (sony_pic_get_fanspeed(&value))
1481 return -EIO;
1482
1483 return snprintf(buffer, PAGE_SIZE, "%d\n", value);
1484}
1485
1486#define SPIC_ATTR(_name, _mode) \
1487struct device_attribute spic_attr_##_name = __ATTR(_name, \
1488 _mode, sony_pic_## _name ##_show, \
1489 sony_pic_## _name ##_store)
1490
1491static SPIC_ATTR(bluetoothpower, 0644);
1492static SPIC_ATTR(wwanpower, 0644);
1493static SPIC_ATTR(fanspeed, 0644);
1494
1495static struct attribute *spic_attributes[] = {
1496 &spic_attr_bluetoothpower.attr,
1497 &spic_attr_wwanpower.attr,
1498 &spic_attr_fanspeed.attr,
1499 NULL
1500};
1501
1502static struct attribute_group spic_attribute_group = {
1503 .attrs = spic_attributes
1504};
1505
1506/******** SONYPI compatibility **********/
1507#ifdef CONFIG_SONY_LAPTOP_OLD
1508
1509/* battery / brightness / temperature addresses */
1510#define SONYPI_BAT_FLAGS 0x81
1511#define SONYPI_LCD_LIGHT 0x96
1512#define SONYPI_BAT1_PCTRM 0xa0
1513#define SONYPI_BAT1_LEFT 0xa2
1514#define SONYPI_BAT1_MAXRT 0xa4
1515#define SONYPI_BAT2_PCTRM 0xa8
1516#define SONYPI_BAT2_LEFT 0xaa
1517#define SONYPI_BAT2_MAXRT 0xac
1518#define SONYPI_BAT1_MAXTK 0xb0
1519#define SONYPI_BAT1_FULL 0xb2
1520#define SONYPI_BAT2_MAXTK 0xb8
1521#define SONYPI_BAT2_FULL 0xba
1522#define SONYPI_TEMP_STATUS 0xC1
1523
1524struct sonypi_compat_s {
1525 struct fasync_struct *fifo_async;
1526 struct kfifo *fifo;
1527 spinlock_t fifo_lock;
1528 wait_queue_head_t fifo_proc_list;
1529 atomic_t open_count;
1530};
1531static struct sonypi_compat_s sonypi_compat = {
1532 .open_count = ATOMIC_INIT(0),
1533};
1534
1535static int sonypi_misc_fasync(int fd, struct file *filp, int on)
1536{
1537 int retval;
1538
1539 retval = fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
1540 if (retval < 0)
1541 return retval;
1542 return 0;
1543}
1544
1545static int sonypi_misc_release(struct inode *inode, struct file *file)
1546{
1547 sonypi_misc_fasync(-1, file, 0);
1548 atomic_dec(&sonypi_compat.open_count);
1549 return 0;
1550}
1551
1552static int sonypi_misc_open(struct inode *inode, struct file *file)
1553{
1554 /* Flush input queue on first open */
1555 if (atomic_inc_return(&sonypi_compat.open_count) == 1)
1556 kfifo_reset(sonypi_compat.fifo);
1557 return 0;
1558}
1559
1560static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
1561 size_t count, loff_t *pos)
1562{
1563 ssize_t ret;
1564 unsigned char c;
1565
1566 if ((kfifo_len(sonypi_compat.fifo) == 0) &&
1567 (file->f_flags & O_NONBLOCK))
1568 return -EAGAIN;
1569
1570 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
1571 kfifo_len(sonypi_compat.fifo) != 0);
1572 if (ret)
1573 return ret;
1574
1575 while (ret < count &&
1576 (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) {
1577 if (put_user(c, buf++))
1578 return -EFAULT;
1579 ret++;
1580 }
1581
1582 if (ret > 0) {
1583 struct inode *inode = file->f_path.dentry->d_inode;
1584 inode->i_atime = current_fs_time(inode->i_sb);
1585 }
1586
1587 return ret;
1588}
1589
1590static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
1591{
1592 poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
1593 if (kfifo_len(sonypi_compat.fifo))
1594 return POLLIN | POLLRDNORM;
1595 return 0;
1596}
1597
1598static int ec_read16(u8 addr, u16 *value)
1599{
1600 u8 val_lb, val_hb;
1601 if (ec_read(addr, &val_lb))
1602 return -1;
1603 if (ec_read(addr + 1, &val_hb))
1604 return -1;
1605 *value = val_lb | (val_hb << 8);
1606 return 0;
1607}
1608
1609static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
1610 unsigned int cmd, unsigned long arg)
1611{
1612 int ret = 0;
1613 void __user *argp = (void __user *)arg;
1614 u8 val8;
1615 u16 val16;
1616 int value;
1617
1618 mutex_lock(&spic_dev.lock);
1619 switch (cmd) {
1620 case SONYPI_IOCGBRT:
1621 if (sony_backlight_device == NULL) {
1622 ret = -EIO;
1623 break;
1624 }
1625 if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) {
1626 ret = -EIO;
1627 break;
1628 }
1629 val8 = ((value & 0xff) - 1) << 5;
1630 if (copy_to_user(argp, &val8, sizeof(val8)))
1631 ret = -EFAULT;
1632 break;
1633 case SONYPI_IOCSBRT:
1634 if (sony_backlight_device == NULL) {
1635 ret = -EIO;
1636 break;
1637 }
1638 if (copy_from_user(&val8, argp, sizeof(val8))) {
1639 ret = -EFAULT;
1640 break;
1641 }
1642 if (acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
1643 (val8 >> 5) + 1, NULL)) {
1644 ret = -EIO;
1645 break;
1646 }
1647 /* sync the backlight device status */
1648 sony_backlight_device->props.brightness =
1649 sony_backlight_get_brightness(sony_backlight_device);
1650 break;
1651 case SONYPI_IOCGBAT1CAP:
1652 if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
1653 ret = -EIO;
1654 break;
1655 }
1656 if (copy_to_user(argp, &val16, sizeof(val16)))
1657 ret = -EFAULT;
1658 break;
1659 case SONYPI_IOCGBAT1REM:
1660 if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
1661 ret = -EIO;
1662 break;
1663 }
1664 if (copy_to_user(argp, &val16, sizeof(val16)))
1665 ret = -EFAULT;
1666 break;
1667 case SONYPI_IOCGBAT2CAP:
1668 if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
1669 ret = -EIO;
1670 break;
1671 }
1672 if (copy_to_user(argp, &val16, sizeof(val16)))
1673 ret = -EFAULT;
1674 break;
1675 case SONYPI_IOCGBAT2REM:
1676 if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
1677 ret = -EIO;
1678 break;
1679 }
1680 if (copy_to_user(argp, &val16, sizeof(val16)))
1681 ret = -EFAULT;
1682 break;
1683 case SONYPI_IOCGBATFLAGS:
1684 if (ec_read(SONYPI_BAT_FLAGS, &val8)) {
1685 ret = -EIO;
1686 break;
1687 }
1688 val8 &= 0x07;
1689 if (copy_to_user(argp, &val8, sizeof(val8)))
1690 ret = -EFAULT;
1691 break;
1692 case SONYPI_IOCGBLUE:
1693 val8 = spic_dev.bluetooth_power;
1694 if (copy_to_user(argp, &val8, sizeof(val8)))
1695 ret = -EFAULT;
1696 break;
1697 case SONYPI_IOCSBLUE:
1698 if (copy_from_user(&val8, argp, sizeof(val8))) {
1699 ret = -EFAULT;
1700 break;
1701 }
1702 __sony_pic_set_bluetoothpower(val8);
1703 break;
1704 /* FAN Controls */
1705 case SONYPI_IOCGFAN:
1706 if (sony_pic_get_fanspeed(&val8)) {
1707 ret = -EIO;
1708 break;
1709 }
1710 if (copy_to_user(argp, &val8, sizeof(val8)))
1711 ret = -EFAULT;
1712 break;
1713 case SONYPI_IOCSFAN:
1714 if (copy_from_user(&val8, argp, sizeof(val8))) {
1715 ret = -EFAULT;
1716 break;
1717 }
1718 if (sony_pic_set_fanspeed(val8))
1719 ret = -EIO;
1720 break;
1721 /* GET Temperature (useful under APM) */
1722 case SONYPI_IOCGTEMP:
1723 if (ec_read(SONYPI_TEMP_STATUS, &val8)) {
1724 ret = -EIO;
1725 break;
1726 }
1727 if (copy_to_user(argp, &val8, sizeof(val8)))
1728 ret = -EFAULT;
1729 break;
1730 default:
1731 ret = -EINVAL;
1732 }
1733 mutex_unlock(&spic_dev.lock);
1734 return ret;
1735}
1736
1737static const struct file_operations sonypi_misc_fops = {
1738 .owner = THIS_MODULE,
1739 .read = sonypi_misc_read,
1740 .poll = sonypi_misc_poll,
1741 .open = sonypi_misc_open,
1742 .release = sonypi_misc_release,
1743 .fasync = sonypi_misc_fasync,
1744 .ioctl = sonypi_misc_ioctl,
1745};
1746
1747static struct miscdevice sonypi_misc_device = {
1748 .minor = MISC_DYNAMIC_MINOR,
1749 .name = "sonypi",
1750 .fops = &sonypi_misc_fops,
1751};
1752
1753static void sonypi_compat_report_event(u8 event)
1754{
1755 kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event));
1756 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
1757 wake_up_interruptible(&sonypi_compat.fifo_proc_list);
1758}
1759
1760static int sonypi_compat_init(void)
1761{
1762 int error;
1763
1764 spin_lock_init(&sonypi_compat.fifo_lock);
1765 sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
1766 &sonypi_compat.fifo_lock);
1767 if (IS_ERR(sonypi_compat.fifo)) {
1768 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
1769 return PTR_ERR(sonypi_compat.fifo);
1770 }
1771
1772 init_waitqueue_head(&sonypi_compat.fifo_proc_list);
1773
1774 if (minor != -1)
1775 sonypi_misc_device.minor = minor;
1776 error = misc_register(&sonypi_misc_device);
1777 if (error) {
1778 printk(KERN_ERR DRV_PFX "misc_register failed\n");
1779 goto err_free_kfifo;
1780 }
1781 if (minor == -1)
1782 printk(KERN_INFO DRV_PFX "device allocated minor is %d\n",
1783 sonypi_misc_device.minor);
1784
1785 return 0;
1786
1787err_free_kfifo:
1788 kfifo_free(sonypi_compat.fifo);
1789 return error;
1790}
1791
1792static void sonypi_compat_exit(void)
1793{
1794 misc_deregister(&sonypi_misc_device);
1795 kfifo_free(sonypi_compat.fifo);
1796}
1797#else
1798static int sonypi_compat_init(void) { return 0; }
1799static void sonypi_compat_exit(void) { }
1800static void sonypi_compat_report_event(u8 event) { }
1801#endif /* CONFIG_SONY_LAPTOP_OLD */
1802
1803/*
1804 * ACPI callbacks
1805 */
1806static acpi_status
1807sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
1808{
1809 u32 i;
1810 struct sony_pic_dev *dev = (struct sony_pic_dev *)context;
1811
1812 switch (resource->type) {
1813 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
1814 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
1815 return AE_OK;
1816
1817 case ACPI_RESOURCE_TYPE_IRQ:
1818 {
1819 struct acpi_resource_irq *p = &resource->data.irq;
1820 struct sony_pic_irq *interrupt = NULL;
1821 if (!p || !p->interrupt_count) {
1822 /*
1823 * IRQ descriptors may have no IRQ# bits set,
1824 * particularly those those w/ _STA disabled
1825 */
1826 dprintk("Blank IRQ resource\n");
1827 return AE_OK;
1828 }
1829 for (i = 0; i < p->interrupt_count; i++) {
1830 if (!p->interrupts[i]) {
1831 printk(KERN_WARNING DRV_PFX
1832 "Invalid IRQ %d\n",
1833 p->interrupts[i]);
1834 continue;
1835 }
1836 interrupt = kzalloc(sizeof(*interrupt),
1837 GFP_KERNEL);
1838 if (!interrupt)
1839 return AE_ERROR;
1840
1841 list_add_tail(&interrupt->list, &dev->interrupts);
1842 interrupt->irq.triggering = p->triggering;
1843 interrupt->irq.polarity = p->polarity;
1844 interrupt->irq.sharable = p->sharable;
1845 interrupt->irq.interrupt_count = 1;
1846 interrupt->irq.interrupts[0] = p->interrupts[i];
1847 }
1848 return AE_OK;
1849 }
1850 case ACPI_RESOURCE_TYPE_IO:
1851 {
1852 struct acpi_resource_io *io = &resource->data.io;
1853 struct sony_pic_ioport *ioport = NULL;
1854 if (!io) {
1855 dprintk("Blank IO resource\n");
1856 return AE_OK;
1857 }
1858
1859 ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
1860 if (!ioport)
1861 return AE_ERROR;
1862
1863 list_add_tail(&ioport->list, &dev->ioports);
1864 memcpy(&ioport->io, io, sizeof(*io));
1865 return AE_OK;
1866 }
1867 default:
1868 dprintk("Resource %d isn't an IRQ nor an IO port\n",
1869 resource->type);
1870
1871 case ACPI_RESOURCE_TYPE_END_TAG:
1872 return AE_OK;
1873 }
1874 return AE_CTRL_TERMINATE;
1875}
1876
1877static int sony_pic_possible_resources(struct acpi_device *device)
1878{
1879 int result = 0;
1880 acpi_status status = AE_OK;
1881
1882 if (!device)
1883 return -EINVAL;
1884
1885 /* get device status */
1886 /* see acpi_pci_link_get_current acpi_pci_link_get_possible */
1887 dprintk("Evaluating _STA\n");
1888 result = acpi_bus_get_status(device);
1889 if (result) {
1890 printk(KERN_WARNING DRV_PFX "Unable to read status\n");
1891 goto end;
1892 }
1893
1894 if (!device->status.enabled)
1895 dprintk("Device disabled\n");
1896 else
1897 dprintk("Device enabled\n");
1898
1899 /*
1900 * Query and parse 'method'
1901 */
1902 dprintk("Evaluating %s\n", METHOD_NAME__PRS);
1903 status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
1904 sony_pic_read_possible_resource, &spic_dev);
1905 if (ACPI_FAILURE(status)) {
1906 printk(KERN_WARNING DRV_PFX
1907 "Failure evaluating %s\n",
1908 METHOD_NAME__PRS);
1909 result = -ENODEV;
1910 }
1911end:
1912 return result;
1913}
1914
1915/*
1916 * Disable the spic device by calling its _DIS method
1917 */
1918static int sony_pic_disable(struct acpi_device *device)
1919{
1920 if (ACPI_FAILURE(acpi_evaluate_object(device->handle, "_DIS", 0, NULL)))
1921 return -ENXIO;
1922
1923 dprintk("Device disabled\n");
1924 return 0;
1925}
1926
1927
1928/*
1929 * Based on drivers/acpi/pci_link.c:acpi_pci_link_set
1930 *
1931 * Call _SRS to set current resources
1932 */
1933static int sony_pic_enable(struct acpi_device *device,
1934 struct sony_pic_ioport *ioport, struct sony_pic_irq *irq)
1935{
1936 acpi_status status;
1937 int result = 0;
1938 struct {
1939 struct acpi_resource io_res;
1940 struct acpi_resource irq_res;
1941 struct acpi_resource end;
1942 } *resource;
1943 struct acpi_buffer buffer = { 0, NULL };
1944
1945 if (!ioport || !irq)
1946 return -EINVAL;
1947
1948 /* init acpi_buffer */
1949 resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
1950 if (!resource)
1951 return -ENOMEM;
1952
1953 buffer.length = sizeof(*resource) + 1;
1954 buffer.pointer = resource;
1955
1956 /* setup io resource */
1957 resource->io_res.type = ACPI_RESOURCE_TYPE_IO;
1958 resource->io_res.length = sizeof(struct acpi_resource);
1959 memcpy(&resource->io_res.data.io, &ioport->io,
1960 sizeof(struct acpi_resource_io));
1961
1962 /* setup irq resource */
1963 resource->irq_res.type = ACPI_RESOURCE_TYPE_IRQ;
1964 resource->irq_res.length = sizeof(struct acpi_resource);
1965 memcpy(&resource->irq_res.data.irq, &irq->irq,
1966 sizeof(struct acpi_resource_irq));
1967 /* we requested a shared irq */
1968 resource->irq_res.data.irq.sharable = ACPI_SHARED;
1969
1970 resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
1971
1972 /* Attempt to set the resource */
1973 dprintk("Evaluating _SRS\n");
1974 status = acpi_set_current_resources(device->handle, &buffer);
1975
1976 /* check for total failure */
1977 if (ACPI_FAILURE(status)) {
1978 printk(KERN_ERR DRV_PFX "Error evaluating _SRS");
1979 result = -ENODEV;
1980 goto end;
1981 }
1982
1983 /* Necessary device initializations calls (from sonypi) */
1984 sony_pic_call1(0x82);
1985 sony_pic_call2(0x81, 0xff);
1986 sony_pic_call1(compat ? 0x92 : 0x82);
1987
1988end:
1989 kfree(resource);
1990 return result;
1991}
1992
1993/*****************
1994 *
1995 * ISR: some event is available
1996 *
1997 *****************/
1998static irqreturn_t sony_pic_irq(int irq, void *dev_id)
1999{
2000 int i, j;
2001 u32 port_val = 0;
2002 u8 ev = 0;
2003 u8 data_mask = 0;
2004 u8 device_event = 0;
2005
2006 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
2007
2008 acpi_os_read_port(dev->cur_ioport->io.minimum, &port_val,
2009 dev->cur_ioport->io.address_length);
2010 ev = port_val & SONY_PIC_EV_MASK;
2011 data_mask = 0xff & (port_val >> (dev->cur_ioport->io.address_length - 8));
2012
2013 dprintk("event (0x%.8x [%.2x] [%.2x]) at port 0x%.4x\n",
2014 port_val, ev, data_mask, dev->cur_ioport->io.minimum);
2015
2016 if (ev == 0x00 || ev == 0xff)
2017 return IRQ_HANDLED;
2018
2019 for (i = 0; sony_pic_eventtypes[i].model; i++) {
2020
2021 if (spic_dev.model != sony_pic_eventtypes[i].model)
2022 continue;
2023
2024 if ((data_mask & sony_pic_eventtypes[i].data) !=
2025 sony_pic_eventtypes[i].data)
2026 continue;
2027
2028 if (!(mask & sony_pic_eventtypes[i].mask))
2029 continue;
2030
2031 for (j = 0; sony_pic_eventtypes[i].events[j].event; j++) {
2032 if (ev == sony_pic_eventtypes[i].events[j].data) {
2033 device_event =
2034 sony_pic_eventtypes[i].events[j].event;
2035 goto found;
2036 }
2037 }
2038 }
2039 return IRQ_HANDLED;
2040
2041found:
2042 sony_laptop_report_input_event(device_event);
2043 acpi_bus_generate_event(spic_dev.acpi_dev, 1, device_event);
2044 sonypi_compat_report_event(device_event);
2045
2046 return IRQ_HANDLED;
2047}
2048
2049/*****************
2050 *
2051 * ACPI driver
2052 *
2053 *****************/
2054static int sony_pic_remove(struct acpi_device *device, int type)
2055{
2056 struct sony_pic_ioport *io, *tmp_io;
2057 struct sony_pic_irq *irq, *tmp_irq;
2058
2059 sonypi_compat_exit();
2060
2061 if (sony_pic_disable(device)) {
2062 printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
2063 return -ENXIO;
2064 }
2065
2066 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
2067 release_region(spic_dev.cur_ioport->io.minimum,
2068 spic_dev.cur_ioport->io.address_length);
2069
2070 sony_laptop_remove_input();
2071
2072 /* pf attrs */
2073 sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
2074 sony_pf_remove();
2075
2076 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
2077 list_del(&io->list);
2078 kfree(io);
2079 }
2080 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
2081 list_del(&irq->list);
2082 kfree(irq);
2083 }
2084 spic_dev.cur_ioport = NULL;
2085 spic_dev.cur_irq = NULL;
2086
2087 dprintk(SONY_PIC_DRIVER_NAME " removed.\n");
2088 return 0;
2089}
2090
2091static int sony_pic_add(struct acpi_device *device)
2092{
2093 int result;
2094 struct sony_pic_ioport *io, *tmp_io;
2095 struct sony_pic_irq *irq, *tmp_irq;
2096
2097 printk(KERN_INFO DRV_PFX "%s v%s.\n",
2098 SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
2099
2100 spic_dev.acpi_dev = device;
2101 strcpy(acpi_device_class(device), "sony/hotkey");
2102 spic_dev.model = sony_pic_detect_device_type();
2103 mutex_init(&spic_dev.lock);
2104
2105 /* read _PRS resources */
2106 result = sony_pic_possible_resources(device);
2107 if (result) {
2108 printk(KERN_ERR DRV_PFX
2109 "Unabe to read possible resources.\n");
2110 goto err_free_resources;
2111 }
2112
2113 /* setup input devices and helper fifo */
2114 result = sony_laptop_setup_input();
2115 if (result) {
2116 printk(KERN_ERR DRV_PFX
2117 "Unabe to create input devices.\n");
2118 goto err_free_resources;
2119 }
2120
2121 /* request io port */
2122 list_for_each_entry(io, &spic_dev.ioports, list) {
2123 if (request_region(io->io.minimum, io->io.address_length,
2124 "Sony Programable I/O Device")) {
2125 dprintk("I/O port: 0x%.4x (0x%.4x) + 0x%.2x\n",
2126 io->io.minimum, io->io.maximum,
2127 io->io.address_length);
2128 spic_dev.cur_ioport = io;
2129 break;
2130 }
2131 }
2132 if (!spic_dev.cur_ioport) {
2133 printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
2134 result = -ENODEV;
2135 goto err_remove_input;
2136 }
2137
2138 /* request IRQ */
2139 list_for_each_entry(irq, &spic_dev.interrupts, list) {
2140 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
2141 IRQF_SHARED, "sony-laptop", &spic_dev)) {
2142 dprintk("IRQ: %d - triggering: %d - "
2143 "polarity: %d - shr: %d\n",
2144 irq->irq.interrupts[0],
2145 irq->irq.triggering,
2146 irq->irq.polarity,
2147 irq->irq.sharable);
2148 spic_dev.cur_irq = irq;
2149 break;
2150 }
2151 }
2152 if (!spic_dev.cur_irq) {
2153 printk(KERN_ERR DRV_PFX "Failed to request_irq.\n");
2154 result = -ENODEV;
2155 goto err_release_region;
2156 }
2157
2158 /* set resource status _SRS */
2159 result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
2160 if (result) {
2161 printk(KERN_ERR DRV_PFX "Couldn't enable device.\n");
2162 goto err_free_irq;
2163 }
2164
2165 spic_dev.bluetooth_power = -1;
2166 /* create device attributes */
2167 result = sony_pf_add();
2168 if (result)
2169 goto err_disable_device;
2170
2171 result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
2172 if (result)
2173 goto err_remove_pf;
2174
2175 if (sonypi_compat_init())
2176 goto err_remove_pf;
2177
2178 return 0;
2179
2180err_remove_pf:
2181 sony_pf_remove();
2182
2183err_disable_device:
2184 sony_pic_disable(device);
2185
2186err_free_irq:
2187 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
2188
2189err_release_region:
2190 release_region(spic_dev.cur_ioport->io.minimum,
2191 spic_dev.cur_ioport->io.address_length);
2192
2193err_remove_input:
2194 sony_laptop_remove_input();
2195
2196err_free_resources:
2197 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
2198 list_del(&io->list);
2199 kfree(io);
2200 }
2201 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
2202 list_del(&irq->list);
2203 kfree(irq);
2204 }
2205 spic_dev.cur_ioport = NULL;
2206 spic_dev.cur_irq = NULL;
2207
2208 return result;
2209}
2210
2211static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
2212{
2213 if (sony_pic_disable(device))
2214 return -ENXIO;
2215 return 0;
2216}
2217
2218static int sony_pic_resume(struct acpi_device *device)
2219{
2220 sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
2221 return 0;
2222}
2223
2224static struct acpi_driver sony_pic_driver = {
2225 .name = SONY_PIC_DRIVER_NAME,
2226 .class = SONY_PIC_CLASS,
2227 .ids = SONY_PIC_HID,
2228 .owner = THIS_MODULE,
2229 .ops = {
2230 .add = sony_pic_add,
2231 .remove = sony_pic_remove,
2232 .suspend = sony_pic_suspend,
2233 .resume = sony_pic_resume,
2234 },
2235};
2236
2237static struct dmi_system_id __initdata sonypi_dmi_table[] = {
2238 {
2239 .ident = "Sony Vaio",
2240 .matches = {
2241 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2242 DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"),
2243 },
2244 },
2245 {
2246 .ident = "Sony Vaio",
2247 .matches = {
2248 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2249 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
2250 },
2251 },
2252 { }
2253};
2254
2255static int __init sony_laptop_init(void)
2256{
2257 int result;
2258
2259 if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
2260 result = acpi_bus_register_driver(&sony_pic_driver);
2261 if (result) {
2262 printk(KERN_ERR DRV_PFX
2263 "Unable to register SPIC driver.");
2264 goto out;
2265 }
2266 }
2267
2268 result = acpi_bus_register_driver(&sony_nc_driver);
2269 if (result) {
2270 printk(KERN_ERR DRV_PFX "Unable to register SNC driver.");
2271 goto out_unregister_pic;
2272 }
2273
2274 return 0;
2275
2276out_unregister_pic:
2277 if (!no_spic)
2278 acpi_bus_unregister_driver(&sony_pic_driver);
2279out:
2280 return result;
556} 2281}
557 2282
558static void __exit sony_acpi_exit(void) 2283static void __exit sony_laptop_exit(void)
559{ 2284{
560 acpi_bus_unregister_driver(&sony_acpi_driver); 2285 acpi_bus_unregister_driver(&sony_nc_driver);
2286 if (!no_spic)
2287 acpi_bus_unregister_driver(&sony_pic_driver);
561} 2288}
562 2289
563module_init(sony_acpi_init); 2290module_init(sony_laptop_init);
564module_exit(sony_acpi_exit); 2291module_exit(sony_laptop_exit);
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
new file mode 100644
index 000000000000..6c36a55cb3d1
--- /dev/null
+++ b/drivers/misc/thinkpad_acpi.c
@@ -0,0 +1,4312 @@
1/*
2 * thinkpad_acpi.c - ThinkPad ACPI Extras
3 *
4 *
5 * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
6 * Copyright (C) 2006-2007 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#define IBM_VERSION "0.14"
25#define TPACPI_SYSFS_VERSION 0x000100
26
27/*
28 * Changelog:
29 * 2007-03-27 0.14 renamed to thinkpad_acpi and moved to
30 * drivers/misc.
31 *
32 * 2006-11-22 0.13 new maintainer
33 * changelog now lives in git commit history, and will
34 * not be updated further in-file.
35 *
36 * 2005-08-17 0.12 fix compilation on 2.6.13-rc kernels
37 * 2005-03-17 0.11 support for 600e, 770x
38 * thanks to Jamie Lentin <lentinj@dial.pipex.com>
39 * support for 770e, G41
40 * G40 and G41 don't have a thinklight
41 * temperatures no longer experimental
42 * experimental brightness control
43 * experimental volume control
44 * experimental fan enable/disable
45 * 2005-01-16 0.10 fix module loading on R30, R31
46 * 2005-01-16 0.9 support for 570, R30, R31
47 * ultrabay support on A22p, A3x
48 * limit arg for cmos, led, beep, drop experimental status
49 * more capable led control on A21e, A22p, T20-22, X20
50 * experimental temperatures and fan speed
51 * experimental embedded controller register dump
52 * mark more functions as __init, drop incorrect __exit
53 * use MODULE_VERSION
54 * thanks to Henrik Brix Andersen <brix@gentoo.org>
55 * fix parameter passing on module loading
56 * thanks to Rusty Russell <rusty@rustcorp.com.au>
57 * thanks to Jim Radford <radford@blackbean.org>
58 * 2004-11-08 0.8 fix init error case, don't return from a macro
59 * thanks to Chris Wright <chrisw@osdl.org>
60 * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20
61 * fix led control on A21e
62 * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device
63 * 2004-10-18 0.5 thinklight support on A21e, G40, R32, T20, T21, X20
64 * proc file format changed
65 * video_switch command
66 * experimental cmos control
67 * experimental led control
68 * experimental acpi sounds
69 * 2004-09-16 0.4 support for module parameters
70 * hotkey mask can be prefixed by 0x
71 * video output switching
72 * video expansion control
73 * ultrabay eject support
74 * removed lcd brightness/on/off control, didn't work
75 * 2004-08-17 0.3 support for R40
76 * lcd off, brightness control
77 * thinklight on/off
78 * 2004-08-14 0.2 support for T series, X20
79 * bluetooth enable/disable
80 * hotkey events disabled by default
81 * removed fan control, currently useless
82 * 2004-08-09 0.1 initial release, support for X series
83 */
84
85#include "thinkpad_acpi.h"
86
87MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
88MODULE_DESCRIPTION(IBM_DESC);
89MODULE_VERSION(IBM_VERSION);
90MODULE_LICENSE("GPL");
91
92/* Please remove this in year 2009 */
93MODULE_ALIAS("ibm_acpi");
94
95#define __unused __attribute__ ((unused))
96
97/****************************************************************************
98 ****************************************************************************
99 *
100 * ACPI Helpers and device model
101 *
102 ****************************************************************************
103 ****************************************************************************/
104
105/*************************************************************************
106 * ACPI basic handles
107 */
108
109static acpi_handle root_handle = NULL;
110
111#define IBM_HANDLE(object, parent, paths...) \
112 static acpi_handle object##_handle; \
113 static acpi_handle *object##_parent = &parent##_handle; \
114 static char *object##_path; \
115 static char *object##_paths[] = { paths }
116
117IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */
118 "\\_SB.PCI.ISA.EC", /* 570 */
119 "\\_SB.PCI0.ISA0.EC0", /* 600e/x, 770e, 770x */
120 "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */
121 "\\_SB.PCI0.AD4S.EC0", /* i1400, R30 */
122 "\\_SB.PCI0.ICH3.EC0", /* R31 */
123 "\\_SB.PCI0.LPC.EC", /* all others */
124 );
125
126IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */
127IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */
128
129
130/*************************************************************************
131 * Misc ACPI handles
132 */
133
134IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */
135 "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */
136 "\\CMS", /* R40, R40e */
137 ); /* all others */
138
139IBM_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */
140 "^HKEY", /* R30, R31 */
141 "HKEY", /* all others */
142 ); /* 570 */
143
144
145/*************************************************************************
146 * ACPI helpers
147 */
148
149static int acpi_evalf(acpi_handle handle,
150 void *res, char *method, char *fmt, ...)
151{
152 char *fmt0 = fmt;
153 struct acpi_object_list params;
154 union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
155 struct acpi_buffer result, *resultp;
156 union acpi_object out_obj;
157 acpi_status status;
158 va_list ap;
159 char res_type;
160 int success;
161 int quiet;
162
163 if (!*fmt) {
164 printk(IBM_ERR "acpi_evalf() called with empty format\n");
165 return 0;
166 }
167
168 if (*fmt == 'q') {
169 quiet = 1;
170 fmt++;
171 } else
172 quiet = 0;
173
174 res_type = *(fmt++);
175
176 params.count = 0;
177 params.pointer = &in_objs[0];
178
179 va_start(ap, fmt);
180 while (*fmt) {
181 char c = *(fmt++);
182 switch (c) {
183 case 'd': /* int */
184 in_objs[params.count].integer.value = va_arg(ap, int);
185 in_objs[params.count++].type = ACPI_TYPE_INTEGER;
186 break;
187 /* add more types as needed */
188 default:
189 printk(IBM_ERR "acpi_evalf() called "
190 "with invalid format character '%c'\n", c);
191 return 0;
192 }
193 }
194 va_end(ap);
195
196 if (res_type != 'v') {
197 result.length = sizeof(out_obj);
198 result.pointer = &out_obj;
199 resultp = &result;
200 } else
201 resultp = NULL;
202
203 status = acpi_evaluate_object(handle, method, &params, resultp);
204
205 switch (res_type) {
206 case 'd': /* int */
207 if (res)
208 *(int *)res = out_obj.integer.value;
209 success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
210 break;
211 case 'v': /* void */
212 success = status == AE_OK;
213 break;
214 /* add more types as needed */
215 default:
216 printk(IBM_ERR "acpi_evalf() called "
217 "with invalid format character '%c'\n", res_type);
218 return 0;
219 }
220
221 if (!success && !quiet)
222 printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
223 method, fmt0, status);
224
225 return success;
226}
227
228static void __unused acpi_print_int(acpi_handle handle, char *method)
229{
230 int i;
231
232 if (acpi_evalf(handle, &i, method, "d"))
233 printk(IBM_INFO "%s = 0x%x\n", method, i);
234 else
235 printk(IBM_ERR "error calling %s\n", method);
236}
237
238static int acpi_ec_read(int i, u8 * p)
239{
240 int v;
241
242 if (ecrd_handle) {
243 if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
244 return 0;
245 *p = v;
246 } else {
247 if (ec_read(i, p) < 0)
248 return 0;
249 }
250
251 return 1;
252}
253
254static int acpi_ec_write(int i, u8 v)
255{
256 if (ecwr_handle) {
257 if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
258 return 0;
259 } else {
260 if (ec_write(i, v) < 0)
261 return 0;
262 }
263
264 return 1;
265}
266
267static int _sta(acpi_handle handle)
268{
269 int status;
270
271 if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
272 status = 0;
273
274 return status;
275}
276
277static int issue_thinkpad_cmos_command(int cmos_cmd)
278{
279 if (!cmos_handle)
280 return -ENXIO;
281
282 if (!acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd))
283 return -EIO;
284
285 return 0;
286}
287
288/*************************************************************************
289 * ACPI device model
290 */
291
292static void drv_acpi_handle_init(char *name,
293 acpi_handle *handle, acpi_handle parent,
294 char **paths, int num_paths, char **path)
295{
296 int i;
297 acpi_status status;
298
299 vdbg_printk(TPACPI_DBG_INIT, "trying to locate ACPI handle for %s\n",
300 name);
301
302 for (i = 0; i < num_paths; i++) {
303 status = acpi_get_handle(parent, paths[i], handle);
304 if (ACPI_SUCCESS(status)) {
305 *path = paths[i];
306 dbg_printk(TPACPI_DBG_INIT,
307 "Found ACPI handle %s for %s\n",
308 *path, name);
309 return;
310 }
311 }
312
313 vdbg_printk(TPACPI_DBG_INIT, "ACPI handle for %s not found\n",
314 name);
315 *handle = NULL;
316}
317
318static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data)
319{
320 struct ibm_struct *ibm = data;
321
322 if (!ibm || !ibm->acpi || !ibm->acpi->notify)
323 return;
324
325 ibm->acpi->notify(ibm, event);
326}
327
328static int __init setup_acpi_notify(struct ibm_struct *ibm)
329{
330 acpi_status status;
331 int rc;
332
333 BUG_ON(!ibm->acpi);
334
335 if (!*ibm->acpi->handle)
336 return 0;
337
338 vdbg_printk(TPACPI_DBG_INIT,
339 "setting up ACPI notify for %s\n", ibm->name);
340
341 rc = acpi_bus_get_device(*ibm->acpi->handle, &ibm->acpi->device);
342 if (rc < 0) {
343 printk(IBM_ERR "acpi_bus_get_device(%s) failed: %d\n",
344 ibm->name, rc);
345 return -ENODEV;
346 }
347
348 acpi_driver_data(ibm->acpi->device) = ibm;
349 sprintf(acpi_device_class(ibm->acpi->device), "%s/%s",
350 IBM_ACPI_EVENT_PREFIX,
351 ibm->name);
352
353 status = acpi_install_notify_handler(*ibm->acpi->handle,
354 ibm->acpi->type, dispatch_acpi_notify, ibm);
355 if (ACPI_FAILURE(status)) {
356 if (status == AE_ALREADY_EXISTS) {
357 printk(IBM_NOTICE "another device driver is already handling %s events\n",
358 ibm->name);
359 } else {
360 printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
361 ibm->name, status);
362 }
363 return -ENODEV;
364 }
365 ibm->flags.acpi_notify_installed = 1;
366 return 0;
367}
368
369static int __init tpacpi_device_add(struct acpi_device *device)
370{
371 return 0;
372}
373
374static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
375{
376 int rc;
377
378 dbg_printk(TPACPI_DBG_INIT,
379 "registering %s as an ACPI driver\n", ibm->name);
380
381 BUG_ON(!ibm->acpi);
382
383 ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
384 if (!ibm->acpi->driver) {
385 printk(IBM_ERR "kzalloc(ibm->driver) failed\n");
386 return -ENOMEM;
387 }
388
389 sprintf(ibm->acpi->driver->name, "%s_%s", IBM_NAME, ibm->name);
390 ibm->acpi->driver->ids = ibm->acpi->hid;
391 ibm->acpi->driver->ops.add = &tpacpi_device_add;
392
393 rc = acpi_bus_register_driver(ibm->acpi->driver);
394 if (rc < 0) {
395 printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
396 ibm->acpi->hid, rc);
397 kfree(ibm->acpi->driver);
398 ibm->acpi->driver = NULL;
399 } else if (!rc)
400 ibm->flags.acpi_driver_registered = 1;
401
402 return rc;
403}
404
405
406/****************************************************************************
407 ****************************************************************************
408 *
409 * Procfs Helpers
410 *
411 ****************************************************************************
412 ****************************************************************************/
413
414static int dispatch_procfs_read(char *page, char **start, off_t off,
415 int count, int *eof, void *data)
416{
417 struct ibm_struct *ibm = data;
418 int len;
419
420 if (!ibm || !ibm->read)
421 return -EINVAL;
422
423 len = ibm->read(page);
424 if (len < 0)
425 return len;
426
427 if (len <= off + count)
428 *eof = 1;
429 *start = page + off;
430 len -= off;
431 if (len > count)
432 len = count;
433 if (len < 0)
434 len = 0;
435
436 return len;
437}
438
439static int dispatch_procfs_write(struct file *file,
440 const char __user * userbuf,
441 unsigned long count, void *data)
442{
443 struct ibm_struct *ibm = data;
444 char *kernbuf;
445 int ret;
446
447 if (!ibm || !ibm->write)
448 return -EINVAL;
449
450 kernbuf = kmalloc(count + 2, GFP_KERNEL);
451 if (!kernbuf)
452 return -ENOMEM;
453
454 if (copy_from_user(kernbuf, userbuf, count)) {
455 kfree(kernbuf);
456 return -EFAULT;
457 }
458
459 kernbuf[count] = 0;
460 strcat(kernbuf, ",");
461 ret = ibm->write(kernbuf);
462 if (ret == 0)
463 ret = count;
464
465 kfree(kernbuf);
466
467 return ret;
468}
469
470static char *next_cmd(char **cmds)
471{
472 char *start = *cmds;
473 char *end;
474
475 while ((end = strchr(start, ',')) && end == start)
476 start = end + 1;
477
478 if (!end)
479 return NULL;
480
481 *end = 0;
482 *cmds = end + 1;
483 return start;
484}
485
486
487/****************************************************************************
488 ****************************************************************************
489 *
490 * Device model: hwmon and platform
491 *
492 ****************************************************************************
493 ****************************************************************************/
494
495static struct platform_device *tpacpi_pdev = NULL;
496static struct class_device *tpacpi_hwmon = NULL;
497
498static struct platform_driver tpacpi_pdriver = {
499 .driver = {
500 .name = IBM_DRVR_NAME,
501 .owner = THIS_MODULE,
502 },
503};
504
505
506/*************************************************************************
507 * thinkpad-acpi driver attributes
508 */
509
510/* interface_version --------------------------------------------------- */
511static ssize_t tpacpi_driver_interface_version_show(
512 struct device_driver *drv,
513 char *buf)
514{
515 return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION);
516}
517
518static DRIVER_ATTR(interface_version, S_IRUGO,
519 tpacpi_driver_interface_version_show, NULL);
520
521/* debug_level --------------------------------------------------------- */
522static ssize_t tpacpi_driver_debug_show(struct device_driver *drv,
523 char *buf)
524{
525 return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level);
526}
527
528static ssize_t tpacpi_driver_debug_store(struct device_driver *drv,
529 const char *buf, size_t count)
530{
531 unsigned long t;
532
533 if (parse_strtoul(buf, 0xffff, &t))
534 return -EINVAL;
535
536 dbg_level = t;
537
538 return count;
539}
540
541static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
542 tpacpi_driver_debug_show, tpacpi_driver_debug_store);
543
544/* version ------------------------------------------------------------- */
545static ssize_t tpacpi_driver_version_show(struct device_driver *drv,
546 char *buf)
547{
548 return snprintf(buf, PAGE_SIZE, "%s v%s\n", IBM_DESC, IBM_VERSION);
549}
550
551static DRIVER_ATTR(version, S_IRUGO,
552 tpacpi_driver_version_show, NULL);
553
554/* --------------------------------------------------------------------- */
555
556static struct driver_attribute* tpacpi_driver_attributes[] = {
557 &driver_attr_debug_level, &driver_attr_version,
558 &driver_attr_interface_version,
559};
560
561static int __init tpacpi_create_driver_attributes(struct device_driver *drv)
562{
563 int i, res;
564
565 i = 0;
566 res = 0;
567 while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) {
568 res = driver_create_file(drv, tpacpi_driver_attributes[i]);
569 i++;
570 }
571
572 return res;
573}
574
575static void tpacpi_remove_driver_attributes(struct device_driver *drv)
576{
577 int i;
578
579 for(i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
580 driver_remove_file(drv, tpacpi_driver_attributes[i]);
581}
582
583/*************************************************************************
584 * sysfs support helpers
585 */
586
587struct attribute_set_obj {
588 struct attribute_set s;
589 struct attribute *a;
590} __attribute__((packed));
591
592static struct attribute_set *create_attr_set(unsigned int max_members,
593 const char* name)
594{
595 struct attribute_set_obj *sobj;
596
597 if (max_members == 0)
598 return NULL;
599
600 /* Allocates space for implicit NULL at the end too */
601 sobj = kzalloc(sizeof(struct attribute_set_obj) +
602 max_members * sizeof(struct attribute *),
603 GFP_KERNEL);
604 if (!sobj)
605 return NULL;
606 sobj->s.max_members = max_members;
607 sobj->s.group.attrs = &sobj->a;
608 sobj->s.group.name = name;
609
610 return &sobj->s;
611}
612
613/* not multi-threaded safe, use it in a single thread per set */
614static int add_to_attr_set(struct attribute_set* s, struct attribute *attr)
615{
616 if (!s || !attr)
617 return -EINVAL;
618
619 if (s->members >= s->max_members)
620 return -ENOMEM;
621
622 s->group.attrs[s->members] = attr;
623 s->members++;
624
625 return 0;
626}
627
628static int add_many_to_attr_set(struct attribute_set* s,
629 struct attribute **attr,
630 unsigned int count)
631{
632 int i, res;
633
634 for (i = 0; i < count; i++) {
635 res = add_to_attr_set(s, attr[i]);
636 if (res)
637 return res;
638 }
639
640 return 0;
641}
642
643static void delete_attr_set(struct attribute_set* s, struct kobject *kobj)
644{
645 sysfs_remove_group(kobj, &s->group);
646 destroy_attr_set(s);
647}
648
649static int parse_strtoul(const char *buf,
650 unsigned long max, unsigned long *value)
651{
652 char *endp;
653
654 *value = simple_strtoul(buf, &endp, 0);
655 while (*endp && isspace(*endp))
656 endp++;
657 if (*endp || *value > max)
658 return -EINVAL;
659
660 return 0;
661}
662
663/****************************************************************************
664 ****************************************************************************
665 *
666 * Subdrivers
667 *
668 ****************************************************************************
669 ****************************************************************************/
670
671/*************************************************************************
672 * thinkpad-acpi init subdriver
673 */
674
675static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
676{
677 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
678 printk(IBM_INFO "%s\n", IBM_URL);
679
680 if (ibm_thinkpad_ec_found)
681 printk(IBM_INFO "ThinkPad EC firmware %s\n",
682 ibm_thinkpad_ec_found);
683
684 return 0;
685}
686
687static int thinkpad_acpi_driver_read(char *p)
688{
689 int len = 0;
690
691 len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC);
692 len += sprintf(p + len, "version:\t%s\n", IBM_VERSION);
693
694 return len;
695}
696
697static struct ibm_struct thinkpad_acpi_driver_data = {
698 .name = "driver",
699 .read = thinkpad_acpi_driver_read,
700};
701
702/*************************************************************************
703 * Hotkey subdriver
704 */
705
706static int hotkey_orig_status;
707static int hotkey_orig_mask;
708
709static struct attribute_set *hotkey_dev_attributes = NULL;
710
711/* sysfs hotkey enable ------------------------------------------------- */
712static ssize_t hotkey_enable_show(struct device *dev,
713 struct device_attribute *attr,
714 char *buf)
715{
716 int res, status, mask;
717
718 res = hotkey_get(&status, &mask);
719 if (res)
720 return res;
721
722 return snprintf(buf, PAGE_SIZE, "%d\n", status);
723}
724
725static ssize_t hotkey_enable_store(struct device *dev,
726 struct device_attribute *attr,
727 const char *buf, size_t count)
728{
729 unsigned long t;
730 int res, status, mask;
731
732 if (parse_strtoul(buf, 1, &t))
733 return -EINVAL;
734
735 res = hotkey_get(&status, &mask);
736 if (!res)
737 res = hotkey_set(t, mask);
738
739 return (res) ? res : count;
740}
741
742static struct device_attribute dev_attr_hotkey_enable =
743 __ATTR(enable, S_IWUSR | S_IRUGO,
744 hotkey_enable_show, hotkey_enable_store);
745
746/* sysfs hotkey mask --------------------------------------------------- */
747static ssize_t hotkey_mask_show(struct device *dev,
748 struct device_attribute *attr,
749 char *buf)
750{
751 int res, status, mask;
752
753 res = hotkey_get(&status, &mask);
754 if (res)
755 return res;
756
757 return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask);
758}
759
760static ssize_t hotkey_mask_store(struct device *dev,
761 struct device_attribute *attr,
762 const char *buf, size_t count)
763{
764 unsigned long t;
765 int res, status, mask;
766
767 if (parse_strtoul(buf, 0xffff, &t))
768 return -EINVAL;
769
770 res = hotkey_get(&status, &mask);
771 if (!res)
772 hotkey_set(status, t);
773
774 return (res) ? res : count;
775}
776
777static struct device_attribute dev_attr_hotkey_mask =
778 __ATTR(mask, S_IWUSR | S_IRUGO,
779 hotkey_mask_show, hotkey_mask_store);
780
781/* sysfs hotkey bios_enabled ------------------------------------------- */
782static ssize_t hotkey_bios_enabled_show(struct device *dev,
783 struct device_attribute *attr,
784 char *buf)
785{
786 return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status);
787}
788
789static struct device_attribute dev_attr_hotkey_bios_enabled =
790 __ATTR(bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
791
792/* sysfs hotkey bios_mask ---------------------------------------------- */
793static ssize_t hotkey_bios_mask_show(struct device *dev,
794 struct device_attribute *attr,
795 char *buf)
796{
797 return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask);
798}
799
800static struct device_attribute dev_attr_hotkey_bios_mask =
801 __ATTR(bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
802
803/* --------------------------------------------------------------------- */
804
805static struct attribute *hotkey_mask_attributes[] = {
806 &dev_attr_hotkey_mask.attr,
807 &dev_attr_hotkey_bios_enabled.attr,
808 &dev_attr_hotkey_bios_mask.attr,
809};
810
811static int __init hotkey_init(struct ibm_init_struct *iibm)
812{
813 int res;
814
815 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
816
817 IBM_ACPIHANDLE_INIT(hkey);
818 mutex_init(&hotkey_mutex);
819
820 /* hotkey not supported on 570 */
821 tp_features.hotkey = hkey_handle != NULL;
822
823 vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n",
824 str_supported(tp_features.hotkey));
825
826 if (tp_features.hotkey) {
827 hotkey_dev_attributes = create_attr_set(4,
828 TPACPI_HOTKEY_SYSFS_GROUP);
829 if (!hotkey_dev_attributes)
830 return -ENOMEM;
831 res = add_to_attr_set(hotkey_dev_attributes,
832 &dev_attr_hotkey_enable.attr);
833 if (res)
834 return res;
835
836 /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
837 A30, R30, R31, T20-22, X20-21, X22-24 */
838 tp_features.hotkey_mask =
839 acpi_evalf(hkey_handle, NULL, "DHKN", "qv");
840
841 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
842 str_supported(tp_features.hotkey_mask));
843
844 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
845 if (!res && tp_features.hotkey_mask) {
846 res = add_many_to_attr_set(hotkey_dev_attributes,
847 hotkey_mask_attributes,
848 ARRAY_SIZE(hotkey_mask_attributes));
849 }
850 if (!res)
851 res = register_attr_set_with_sysfs(
852 hotkey_dev_attributes,
853 &tpacpi_pdev->dev.kobj);
854
855 if (res)
856 return res;
857 }
858
859 return (tp_features.hotkey)? 0 : 1;
860}
861
862static void hotkey_exit(void)
863{
864 int res;
865
866 if (tp_features.hotkey) {
867 dbg_printk(TPACPI_DBG_EXIT, "restoring original hotkey mask\n");
868 res = hotkey_set(hotkey_orig_status, hotkey_orig_mask);
869 if (res)
870 printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n");
871 }
872
873 if (hotkey_dev_attributes) {
874 delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
875 hotkey_dev_attributes = NULL;
876 }
877}
878
879static void hotkey_notify(struct ibm_struct *ibm, u32 event)
880{
881 int hkey;
882
883 if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d"))
884 acpi_bus_generate_event(ibm->acpi->device, event, hkey);
885 else {
886 printk(IBM_ERR "unknown hotkey event %d\n", event);
887 acpi_bus_generate_event(ibm->acpi->device, event, 0);
888 }
889}
890
891/*
892 * Call with hotkey_mutex held
893 */
894static int hotkey_get(int *status, int *mask)
895{
896 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
897 return -EIO;
898
899 if (tp_features.hotkey_mask)
900 if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
901 return -EIO;
902
903 return 0;
904}
905
906/*
907 * Call with hotkey_mutex held
908 */
909static int hotkey_set(int status, int mask)
910{
911 int i;
912
913 if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
914 return -EIO;
915
916 if (tp_features.hotkey_mask)
917 for (i = 0; i < 32; i++) {
918 int bit = ((1 << i) & mask) != 0;
919 if (!acpi_evalf(hkey_handle,
920 NULL, "MHKM", "vdd", i + 1, bit))
921 return -EIO;
922 }
923
924 return 0;
925}
926
927/* procfs -------------------------------------------------------------- */
928static int hotkey_read(char *p)
929{
930 int res, status, mask;
931 int len = 0;
932
933 if (!tp_features.hotkey) {
934 len += sprintf(p + len, "status:\t\tnot supported\n");
935 return len;
936 }
937
938 res = mutex_lock_interruptible(&hotkey_mutex);
939 if (res < 0)
940 return res;
941 res = hotkey_get(&status, &mask);
942 mutex_unlock(&hotkey_mutex);
943 if (res)
944 return res;
945
946 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
947 if (tp_features.hotkey_mask) {
948 len += sprintf(p + len, "mask:\t\t0x%04x\n", mask);
949 len += sprintf(p + len,
950 "commands:\tenable, disable, reset, <mask>\n");
951 } else {
952 len += sprintf(p + len, "mask:\t\tnot supported\n");
953 len += sprintf(p + len, "commands:\tenable, disable, reset\n");
954 }
955
956 return len;
957}
958
959static int hotkey_write(char *buf)
960{
961 int res, status, mask;
962 char *cmd;
963 int do_cmd = 0;
964
965 if (!tp_features.hotkey)
966 return -ENODEV;
967
968 res = mutex_lock_interruptible(&hotkey_mutex);
969 if (res < 0)
970 return res;
971
972 res = hotkey_get(&status, &mask);
973 if (res)
974 goto errexit;
975
976 res = 0;
977 while ((cmd = next_cmd(&buf))) {
978 if (strlencmp(cmd, "enable") == 0) {
979 status = 1;
980 } else if (strlencmp(cmd, "disable") == 0) {
981 status = 0;
982 } else if (strlencmp(cmd, "reset") == 0) {
983 status = hotkey_orig_status;
984 mask = hotkey_orig_mask;
985 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
986 /* mask set */
987 } else if (sscanf(cmd, "%x", &mask) == 1) {
988 /* mask set */
989 } else {
990 res = -EINVAL;
991 goto errexit;
992 }
993 do_cmd = 1;
994 }
995
996 if (do_cmd)
997 res = hotkey_set(status, mask);
998
999errexit:
1000 mutex_unlock(&hotkey_mutex);
1001 return res;
1002}
1003
1004static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = {
1005 .hid = IBM_HKEY_HID,
1006 .notify = hotkey_notify,
1007 .handle = &hkey_handle,
1008 .type = ACPI_DEVICE_NOTIFY,
1009};
1010
1011static struct ibm_struct hotkey_driver_data = {
1012 .name = "hotkey",
1013 .read = hotkey_read,
1014 .write = hotkey_write,
1015 .exit = hotkey_exit,
1016 .acpi = &ibm_hotkey_acpidriver,
1017};
1018
1019/*************************************************************************
1020 * Bluetooth subdriver
1021 */
1022
1023/* sysfs bluetooth enable ---------------------------------------------- */
1024static ssize_t bluetooth_enable_show(struct device *dev,
1025 struct device_attribute *attr,
1026 char *buf)
1027{
1028 int status;
1029
1030 status = bluetooth_get_radiosw();
1031 if (status < 0)
1032 return status;
1033
1034 return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
1035}
1036
1037static ssize_t bluetooth_enable_store(struct device *dev,
1038 struct device_attribute *attr,
1039 const char *buf, size_t count)
1040{
1041 unsigned long t;
1042 int res;
1043
1044 if (parse_strtoul(buf, 1, &t))
1045 return -EINVAL;
1046
1047 res = bluetooth_set_radiosw(t);
1048
1049 return (res) ? res : count;
1050}
1051
1052static struct device_attribute dev_attr_bluetooth_enable =
1053 __ATTR(enable, S_IWUSR | S_IRUGO,
1054 bluetooth_enable_show, bluetooth_enable_store);
1055
1056/* --------------------------------------------------------------------- */
1057
1058static struct attribute *bluetooth_attributes[] = {
1059 &dev_attr_bluetooth_enable.attr,
1060 NULL
1061};
1062
1063static const struct attribute_group bluetooth_attr_group = {
1064 .name = TPACPI_BLUETH_SYSFS_GROUP,
1065 .attrs = bluetooth_attributes,
1066};
1067
1068static int __init bluetooth_init(struct ibm_init_struct *iibm)
1069{
1070 int res;
1071 int status = 0;
1072
1073 vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n");
1074
1075 IBM_ACPIHANDLE_INIT(hkey);
1076
1077 /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
1078 G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
1079 tp_features.bluetooth = hkey_handle &&
1080 acpi_evalf(hkey_handle, &status, "GBDC", "qd");
1081
1082 vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s, status 0x%02x\n",
1083 str_supported(tp_features.bluetooth),
1084 status);
1085
1086 if (tp_features.bluetooth) {
1087 if (!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
1088 /* no bluetooth hardware present in system */
1089 tp_features.bluetooth = 0;
1090 dbg_printk(TPACPI_DBG_INIT,
1091 "bluetooth hardware not installed\n");
1092 } else {
1093 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
1094 &bluetooth_attr_group);
1095 if (res)
1096 return res;
1097 }
1098 }
1099
1100 return (tp_features.bluetooth)? 0 : 1;
1101}
1102
1103static void bluetooth_exit(void)
1104{
1105 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
1106 &bluetooth_attr_group);
1107}
1108
1109static int bluetooth_get_radiosw(void)
1110{
1111 int status;
1112
1113 if (!tp_features.bluetooth)
1114 return -ENODEV;
1115
1116 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
1117 return -EIO;
1118
1119 return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0);
1120}
1121
1122static int bluetooth_set_radiosw(int radio_on)
1123{
1124 int status;
1125
1126 if (!tp_features.bluetooth)
1127 return -ENODEV;
1128
1129 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
1130 return -EIO;
1131 if (radio_on)
1132 status |= TP_ACPI_BLUETOOTH_RADIOSSW;
1133 else
1134 status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
1135 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
1136 return -EIO;
1137
1138 return 0;
1139}
1140
1141/* procfs -------------------------------------------------------------- */
1142static int bluetooth_read(char *p)
1143{
1144 int len = 0;
1145 int status = bluetooth_get_radiosw();
1146
1147 if (!tp_features.bluetooth)
1148 len += sprintf(p + len, "status:\t\tnot supported\n");
1149 else {
1150 len += sprintf(p + len, "status:\t\t%s\n",
1151 (status)? "enabled" : "disabled");
1152 len += sprintf(p + len, "commands:\tenable, disable\n");
1153 }
1154
1155 return len;
1156}
1157
1158static int bluetooth_write(char *buf)
1159{
1160 char *cmd;
1161
1162 if (!tp_features.bluetooth)
1163 return -ENODEV;
1164
1165 while ((cmd = next_cmd(&buf))) {
1166 if (strlencmp(cmd, "enable") == 0) {
1167 bluetooth_set_radiosw(1);
1168 } else if (strlencmp(cmd, "disable") == 0) {
1169 bluetooth_set_radiosw(0);
1170 } else
1171 return -EINVAL;
1172 }
1173
1174 return 0;
1175}
1176
1177static struct ibm_struct bluetooth_driver_data = {
1178 .name = "bluetooth",
1179 .read = bluetooth_read,
1180 .write = bluetooth_write,
1181 .exit = bluetooth_exit,
1182};
1183
1184/*************************************************************************
1185 * Wan subdriver
1186 */
1187
1188/* sysfs wan enable ---------------------------------------------------- */
1189static ssize_t wan_enable_show(struct device *dev,
1190 struct device_attribute *attr,
1191 char *buf)
1192{
1193 int status;
1194
1195 status = wan_get_radiosw();
1196 if (status < 0)
1197 return status;
1198
1199 return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
1200}
1201
1202static ssize_t wan_enable_store(struct device *dev,
1203 struct device_attribute *attr,
1204 const char *buf, size_t count)
1205{
1206 unsigned long t;
1207 int res;
1208
1209 if (parse_strtoul(buf, 1, &t))
1210 return -EINVAL;
1211
1212 res = wan_set_radiosw(t);
1213
1214 return (res) ? res : count;
1215}
1216
1217static struct device_attribute dev_attr_wan_enable =
1218 __ATTR(enable, S_IWUSR | S_IRUGO,
1219 wan_enable_show, wan_enable_store);
1220
1221/* --------------------------------------------------------------------- */
1222
1223static struct attribute *wan_attributes[] = {
1224 &dev_attr_wan_enable.attr,
1225 NULL
1226};
1227
1228static const struct attribute_group wan_attr_group = {
1229 .name = TPACPI_WAN_SYSFS_GROUP,
1230 .attrs = wan_attributes,
1231};
1232
1233static int __init wan_init(struct ibm_init_struct *iibm)
1234{
1235 int res;
1236 int status = 0;
1237
1238 vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n");
1239
1240 IBM_ACPIHANDLE_INIT(hkey);
1241
1242 tp_features.wan = hkey_handle &&
1243 acpi_evalf(hkey_handle, &status, "GWAN", "qd");
1244
1245 vdbg_printk(TPACPI_DBG_INIT, "wan is %s, status 0x%02x\n",
1246 str_supported(tp_features.wan),
1247 status);
1248
1249 if (tp_features.wan) {
1250 if (!(status & TP_ACPI_WANCARD_HWPRESENT)) {
1251 /* no wan hardware present in system */
1252 tp_features.wan = 0;
1253 dbg_printk(TPACPI_DBG_INIT,
1254 "wan hardware not installed\n");
1255 } else {
1256 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
1257 &wan_attr_group);
1258 if (res)
1259 return res;
1260 }
1261 }
1262
1263 return (tp_features.wan)? 0 : 1;
1264}
1265
1266static void wan_exit(void)
1267{
1268 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
1269 &wan_attr_group);
1270}
1271
1272static int wan_get_radiosw(void)
1273{
1274 int status;
1275
1276 if (!tp_features.wan)
1277 return -ENODEV;
1278
1279 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
1280 return -EIO;
1281
1282 return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0);
1283}
1284
1285static int wan_set_radiosw(int radio_on)
1286{
1287 int status;
1288
1289 if (!tp_features.wan)
1290 return -ENODEV;
1291
1292 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
1293 return -EIO;
1294 if (radio_on)
1295 status |= TP_ACPI_WANCARD_RADIOSSW;
1296 else
1297 status &= ~TP_ACPI_WANCARD_RADIOSSW;
1298 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
1299 return -EIO;
1300
1301 return 0;
1302}
1303
1304/* procfs -------------------------------------------------------------- */
1305static int wan_read(char *p)
1306{
1307 int len = 0;
1308 int status = wan_get_radiosw();
1309
1310 if (!tp_features.wan)
1311 len += sprintf(p + len, "status:\t\tnot supported\n");
1312 else {
1313 len += sprintf(p + len, "status:\t\t%s\n",
1314 (status)? "enabled" : "disabled");
1315 len += sprintf(p + len, "commands:\tenable, disable\n");
1316 }
1317
1318 return len;
1319}
1320
1321static int wan_write(char *buf)
1322{
1323 char *cmd;
1324
1325 if (!tp_features.wan)
1326 return -ENODEV;
1327
1328 while ((cmd = next_cmd(&buf))) {
1329 if (strlencmp(cmd, "enable") == 0) {
1330 wan_set_radiosw(1);
1331 } else if (strlencmp(cmd, "disable") == 0) {
1332 wan_set_radiosw(0);
1333 } else
1334 return -EINVAL;
1335 }
1336
1337 return 0;
1338}
1339
1340static struct ibm_struct wan_driver_data = {
1341 .name = "wan",
1342 .read = wan_read,
1343 .write = wan_write,
1344 .exit = wan_exit,
1345 .flags.experimental = 1,
1346};
1347
1348/*************************************************************************
1349 * Video subdriver
1350 */
1351
1352static enum video_access_mode video_supported;
1353static int video_orig_autosw;
1354
1355IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */
1356 "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */
1357 "\\_SB.PCI0.VID0", /* 770e */
1358 "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */
1359 "\\_SB.PCI0.AGP.VID", /* all others */
1360 ); /* R30, R31 */
1361
1362IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */
1363
1364static int __init video_init(struct ibm_init_struct *iibm)
1365{
1366 int ivga;
1367
1368 vdbg_printk(TPACPI_DBG_INIT, "initializing video subdriver\n");
1369
1370 IBM_ACPIHANDLE_INIT(vid);
1371 IBM_ACPIHANDLE_INIT(vid2);
1372
1373 if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
1374 /* G41, assume IVGA doesn't change */
1375 vid_handle = vid2_handle;
1376
1377 if (!vid_handle)
1378 /* video switching not supported on R30, R31 */
1379 video_supported = TPACPI_VIDEO_NONE;
1380 else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
1381 /* 570 */
1382 video_supported = TPACPI_VIDEO_570;
1383 else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
1384 /* 600e/x, 770e, 770x */
1385 video_supported = TPACPI_VIDEO_770;
1386 else
1387 /* all others */
1388 video_supported = TPACPI_VIDEO_NEW;
1389
1390 vdbg_printk(TPACPI_DBG_INIT, "video is %s, mode %d\n",
1391 str_supported(video_supported != TPACPI_VIDEO_NONE),
1392 video_supported);
1393
1394 return (video_supported != TPACPI_VIDEO_NONE)? 0 : 1;
1395}
1396
1397static void video_exit(void)
1398{
1399 dbg_printk(TPACPI_DBG_EXIT,
1400 "restoring original video autoswitch mode\n");
1401 if (video_autosw_set(video_orig_autosw))
1402 printk(IBM_ERR "error while trying to restore original "
1403 "video autoswitch mode\n");
1404}
1405
1406static int video_outputsw_get(void)
1407{
1408 int status = 0;
1409 int i;
1410
1411 switch (video_supported) {
1412 case TPACPI_VIDEO_570:
1413 if (!acpi_evalf(NULL, &i, "\\_SB.PHS", "dd",
1414 TP_ACPI_VIDEO_570_PHSCMD))
1415 return -EIO;
1416 status = i & TP_ACPI_VIDEO_570_PHSMASK;
1417 break;
1418 case TPACPI_VIDEO_770:
1419 if (!acpi_evalf(NULL, &i, "\\VCDL", "d"))
1420 return -EIO;
1421 if (i)
1422 status |= TP_ACPI_VIDEO_S_LCD;
1423 if (!acpi_evalf(NULL, &i, "\\VCDC", "d"))
1424 return -EIO;
1425 if (i)
1426 status |= TP_ACPI_VIDEO_S_CRT;
1427 break;
1428 case TPACPI_VIDEO_NEW:
1429 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1) ||
1430 !acpi_evalf(NULL, &i, "\\VCDC", "d"))
1431 return -EIO;
1432 if (i)
1433 status |= TP_ACPI_VIDEO_S_CRT;
1434
1435 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0) ||
1436 !acpi_evalf(NULL, &i, "\\VCDL", "d"))
1437 return -EIO;
1438 if (i)
1439 status |= TP_ACPI_VIDEO_S_LCD;
1440 if (!acpi_evalf(NULL, &i, "\\VCDD", "d"))
1441 return -EIO;
1442 if (i)
1443 status |= TP_ACPI_VIDEO_S_DVI;
1444 break;
1445 default:
1446 return -ENOSYS;
1447 }
1448
1449 return status;
1450}
1451
1452static int video_outputsw_set(int status)
1453{
1454 int autosw;
1455 int res = 0;
1456
1457 switch (video_supported) {
1458 case TPACPI_VIDEO_570:
1459 res = acpi_evalf(NULL, NULL,
1460 "\\_SB.PHS2", "vdd",
1461 TP_ACPI_VIDEO_570_PHS2CMD,
1462 status | TP_ACPI_VIDEO_570_PHS2SET);
1463 break;
1464 case TPACPI_VIDEO_770:
1465 autosw = video_autosw_get();
1466 if (autosw < 0)
1467 return autosw;
1468
1469 res = video_autosw_set(1);
1470 if (res)
1471 return res;
1472 res = acpi_evalf(vid_handle, NULL,
1473 "ASWT", "vdd", status * 0x100, 0);
1474 if (!autosw && video_autosw_set(autosw)) {
1475 printk(IBM_ERR "video auto-switch left enabled due to error\n");
1476 return -EIO;
1477 }
1478 break;
1479 case TPACPI_VIDEO_NEW:
1480 res = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
1481 acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
1482 break;
1483 default:
1484 return -ENOSYS;
1485 }
1486
1487 return (res)? 0 : -EIO;
1488}
1489
1490static int video_autosw_get(void)
1491{
1492 int autosw = 0;
1493
1494 switch (video_supported) {
1495 case TPACPI_VIDEO_570:
1496 if (!acpi_evalf(vid_handle, &autosw, "SWIT", "d"))
1497 return -EIO;
1498 break;
1499 case TPACPI_VIDEO_770:
1500 case TPACPI_VIDEO_NEW:
1501 if (!acpi_evalf(vid_handle, &autosw, "^VDEE", "d"))
1502 return -EIO;
1503 break;
1504 default:
1505 return -ENOSYS;
1506 }
1507
1508 return autosw & 1;
1509}
1510
1511static int video_autosw_set(int enable)
1512{
1513 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable)? 1 : 0))
1514 return -EIO;
1515 return 0;
1516}
1517
1518static int video_outputsw_cycle(void)
1519{
1520 int autosw = video_autosw_get();
1521 int res;
1522
1523 if (autosw < 0)
1524 return autosw;
1525
1526 switch (video_supported) {
1527 case TPACPI_VIDEO_570:
1528 res = video_autosw_set(1);
1529 if (res)
1530 return res;
1531 res = acpi_evalf(ec_handle, NULL, "_Q16", "v");
1532 break;
1533 case TPACPI_VIDEO_770:
1534 case TPACPI_VIDEO_NEW:
1535 res = video_autosw_set(1);
1536 if (res)
1537 return res;
1538 res = acpi_evalf(vid_handle, NULL, "VSWT", "v");
1539 break;
1540 default:
1541 return -ENOSYS;
1542 }
1543 if (!autosw && video_autosw_set(autosw)) {
1544 printk(IBM_ERR "video auto-switch left enabled due to error\n");
1545 return -EIO;
1546 }
1547
1548 return (res)? 0 : -EIO;
1549}
1550
1551static int video_expand_toggle(void)
1552{
1553 switch (video_supported) {
1554 case TPACPI_VIDEO_570:
1555 return acpi_evalf(ec_handle, NULL, "_Q17", "v")?
1556 0 : -EIO;
1557 case TPACPI_VIDEO_770:
1558 return acpi_evalf(vid_handle, NULL, "VEXP", "v")?
1559 0 : -EIO;
1560 case TPACPI_VIDEO_NEW:
1561 return acpi_evalf(NULL, NULL, "\\VEXP", "v")?
1562 0 : -EIO;
1563 default:
1564 return -ENOSYS;
1565 }
1566 /* not reached */
1567}
1568
1569static int video_read(char *p)
1570{
1571 int status, autosw;
1572 int len = 0;
1573
1574 if (video_supported == TPACPI_VIDEO_NONE) {
1575 len += sprintf(p + len, "status:\t\tnot supported\n");
1576 return len;
1577 }
1578
1579 status = video_outputsw_get();
1580 if (status < 0)
1581 return status;
1582
1583 autosw = video_autosw_get();
1584 if (autosw < 0)
1585 return autosw;
1586
1587 len += sprintf(p + len, "status:\t\tsupported\n");
1588 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
1589 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
1590 if (video_supported == TPACPI_VIDEO_NEW)
1591 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
1592 len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
1593 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
1594 len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
1595 if (video_supported == TPACPI_VIDEO_NEW)
1596 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
1597 len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
1598 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
1599
1600 return len;
1601}
1602
1603static int video_write(char *buf)
1604{
1605 char *cmd;
1606 int enable, disable, status;
1607 int res;
1608
1609 if (video_supported == TPACPI_VIDEO_NONE)
1610 return -ENODEV;
1611
1612 enable = 0;
1613 disable = 0;
1614
1615 while ((cmd = next_cmd(&buf))) {
1616 if (strlencmp(cmd, "lcd_enable") == 0) {
1617 enable |= TP_ACPI_VIDEO_S_LCD;
1618 } else if (strlencmp(cmd, "lcd_disable") == 0) {
1619 disable |= TP_ACPI_VIDEO_S_LCD;
1620 } else if (strlencmp(cmd, "crt_enable") == 0) {
1621 enable |= TP_ACPI_VIDEO_S_CRT;
1622 } else if (strlencmp(cmd, "crt_disable") == 0) {
1623 disable |= TP_ACPI_VIDEO_S_CRT;
1624 } else if (video_supported == TPACPI_VIDEO_NEW &&
1625 strlencmp(cmd, "dvi_enable") == 0) {
1626 enable |= TP_ACPI_VIDEO_S_DVI;
1627 } else if (video_supported == TPACPI_VIDEO_NEW &&
1628 strlencmp(cmd, "dvi_disable") == 0) {
1629 disable |= TP_ACPI_VIDEO_S_DVI;
1630 } else if (strlencmp(cmd, "auto_enable") == 0) {
1631 res = video_autosw_set(1);
1632 if (res)
1633 return res;
1634 } else if (strlencmp(cmd, "auto_disable") == 0) {
1635 res = video_autosw_set(0);
1636 if (res)
1637 return res;
1638 } else if (strlencmp(cmd, "video_switch") == 0) {
1639 res = video_outputsw_cycle();
1640 if (res)
1641 return res;
1642 } else if (strlencmp(cmd, "expand_toggle") == 0) {
1643 res = video_expand_toggle();
1644 if (res)
1645 return res;
1646 } else
1647 return -EINVAL;
1648 }
1649
1650 if (enable || disable) {
1651 status = video_outputsw_get();
1652 if (status < 0)
1653 return status;
1654 res = video_outputsw_set((status & ~disable) | enable);
1655 if (res)
1656 return res;
1657 }
1658
1659 return 0;
1660}
1661
1662static struct ibm_struct video_driver_data = {
1663 .name = "video",
1664 .read = video_read,
1665 .write = video_write,
1666 .exit = video_exit,
1667};
1668
1669/*************************************************************************
1670 * Light (thinklight) subdriver
1671 */
1672
1673IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */
1674IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */
1675
1676static int __init light_init(struct ibm_init_struct *iibm)
1677{
1678 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
1679
1680 IBM_ACPIHANDLE_INIT(ledb);
1681 IBM_ACPIHANDLE_INIT(lght);
1682 IBM_ACPIHANDLE_INIT(cmos);
1683
1684 /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
1685 tp_features.light = (cmos_handle || lght_handle) && !ledb_handle;
1686
1687 if (tp_features.light)
1688 /* light status not supported on
1689 570, 600e/x, 770e, 770x, G4x, R30, R31, R32, X20 */
1690 tp_features.light_status =
1691 acpi_evalf(ec_handle, NULL, "KBLT", "qv");
1692
1693 vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
1694 str_supported(tp_features.light));
1695
1696 return (tp_features.light)? 0 : 1;
1697}
1698
1699static int light_read(char *p)
1700{
1701 int len = 0;
1702 int status = 0;
1703
1704 if (!tp_features.light) {
1705 len += sprintf(p + len, "status:\t\tnot supported\n");
1706 } else if (!tp_features.light_status) {
1707 len += sprintf(p + len, "status:\t\tunknown\n");
1708 len += sprintf(p + len, "commands:\ton, off\n");
1709 } else {
1710 if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
1711 return -EIO;
1712 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
1713 len += sprintf(p + len, "commands:\ton, off\n");
1714 }
1715
1716 return len;
1717}
1718
1719static int light_write(char *buf)
1720{
1721 int cmos_cmd, lght_cmd;
1722 char *cmd;
1723 int success;
1724
1725 if (!tp_features.light)
1726 return -ENODEV;
1727
1728 while ((cmd = next_cmd(&buf))) {
1729 if (strlencmp(cmd, "on") == 0) {
1730 cmos_cmd = 0x0c;
1731 lght_cmd = 1;
1732 } else if (strlencmp(cmd, "off") == 0) {
1733 cmos_cmd = 0x0d;
1734 lght_cmd = 0;
1735 } else
1736 return -EINVAL;
1737
1738 success = cmos_handle ?
1739 acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
1740 acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
1741 if (!success)
1742 return -EIO;
1743 }
1744
1745 return 0;
1746}
1747
1748static struct ibm_struct light_driver_data = {
1749 .name = "light",
1750 .read = light_read,
1751 .write = light_write,
1752};
1753
1754/*************************************************************************
1755 * Dock subdriver
1756 */
1757
1758#ifdef CONFIG_THINKPAD_ACPI_DOCK
1759
1760IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
1761 "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
1762 "\\_SB.PCI0.PCI1.DOCK", /* all others */
1763 "\\_SB.PCI.ISA.SLCE", /* 570 */
1764 ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
1765
1766/* don't list other alternatives as we install a notify handler on the 570 */
1767IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
1768
1769static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = {
1770 {
1771 .notify = dock_notify,
1772 .handle = &dock_handle,
1773 .type = ACPI_SYSTEM_NOTIFY,
1774 },
1775 {
1776 .hid = IBM_PCI_HID,
1777 .notify = dock_notify,
1778 .handle = &pci_handle,
1779 .type = ACPI_SYSTEM_NOTIFY,
1780 },
1781};
1782
1783static struct ibm_struct dock_driver_data[2] = {
1784 {
1785 .name = "dock",
1786 .read = dock_read,
1787 .write = dock_write,
1788 .acpi = &ibm_dock_acpidriver[0],
1789 },
1790 {
1791 .name = "dock",
1792 .acpi = &ibm_dock_acpidriver[1],
1793 },
1794};
1795
1796#define dock_docked() (_sta(dock_handle) & 1)
1797
1798static int __init dock_init(struct ibm_init_struct *iibm)
1799{
1800 vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n");
1801
1802 IBM_ACPIHANDLE_INIT(dock);
1803
1804 vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n",
1805 str_supported(dock_handle != NULL));
1806
1807 return (dock_handle)? 0 : 1;
1808}
1809
1810static int __init dock_init2(struct ibm_init_struct *iibm)
1811{
1812 int dock2_needed;
1813
1814 vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver part 2\n");
1815
1816 if (dock_driver_data[0].flags.acpi_driver_registered &&
1817 dock_driver_data[0].flags.acpi_notify_installed) {
1818 IBM_ACPIHANDLE_INIT(pci);
1819 dock2_needed = (pci_handle != NULL);
1820 vdbg_printk(TPACPI_DBG_INIT,
1821 "dock PCI handler for the TP 570 is %s\n",
1822 str_supported(dock2_needed));
1823 } else {
1824 vdbg_printk(TPACPI_DBG_INIT,
1825 "dock subdriver part 2 not required\n");
1826 dock2_needed = 0;
1827 }
1828
1829 return (dock2_needed)? 0 : 1;
1830}
1831
1832static void dock_notify(struct ibm_struct *ibm, u32 event)
1833{
1834 int docked = dock_docked();
1835 int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, IBM_PCI_HID);
1836
1837 if (event == 1 && !pci) /* 570 */
1838 acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */
1839 else if (event == 1 && pci) /* 570 */
1840 acpi_bus_generate_event(ibm->acpi->device, event, 3); /* dock */
1841 else if (event == 3 && docked)
1842 acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */
1843 else if (event == 3 && !docked)
1844 acpi_bus_generate_event(ibm->acpi->device, event, 2); /* undock */
1845 else if (event == 0 && docked)
1846 acpi_bus_generate_event(ibm->acpi->device, event, 3); /* dock */
1847 else {
1848 printk(IBM_ERR "unknown dock event %d, status %d\n",
1849 event, _sta(dock_handle));
1850 acpi_bus_generate_event(ibm->acpi->device, event, 0); /* unknown */
1851 }
1852}
1853
1854static int dock_read(char *p)
1855{
1856 int len = 0;
1857 int docked = dock_docked();
1858
1859 if (!dock_handle)
1860 len += sprintf(p + len, "status:\t\tnot supported\n");
1861 else if (!docked)
1862 len += sprintf(p + len, "status:\t\tundocked\n");
1863 else {
1864 len += sprintf(p + len, "status:\t\tdocked\n");
1865 len += sprintf(p + len, "commands:\tdock, undock\n");
1866 }
1867
1868 return len;
1869}
1870
1871static int dock_write(char *buf)
1872{
1873 char *cmd;
1874
1875 if (!dock_docked())
1876 return -ENODEV;
1877
1878 while ((cmd = next_cmd(&buf))) {
1879 if (strlencmp(cmd, "undock") == 0) {
1880 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
1881 !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
1882 return -EIO;
1883 } else if (strlencmp(cmd, "dock") == 0) {
1884 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
1885 return -EIO;
1886 } else
1887 return -EINVAL;
1888 }
1889
1890 return 0;
1891}
1892
1893#endif /* CONFIG_THINKPAD_ACPI_DOCK */
1894
1895/*************************************************************************
1896 * Bay subdriver
1897 */
1898
1899#ifdef CONFIG_THINKPAD_ACPI_BAY
1900IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
1901 "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
1902 "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
1903 "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
1904 ); /* A21e, R30, R31 */
1905IBM_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */
1906 "_EJ0", /* all others */
1907 ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
1908IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
1909 "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
1910 ); /* all others */
1911IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
1912 "_EJ0", /* 770x */
1913 ); /* all others */
1914
1915static int __init bay_init(struct ibm_init_struct *iibm)
1916{
1917 vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n");
1918
1919 IBM_ACPIHANDLE_INIT(bay);
1920 if (bay_handle)
1921 IBM_ACPIHANDLE_INIT(bay_ej);
1922 IBM_ACPIHANDLE_INIT(bay2);
1923 if (bay2_handle)
1924 IBM_ACPIHANDLE_INIT(bay2_ej);
1925
1926 tp_features.bay_status = bay_handle &&
1927 acpi_evalf(bay_handle, NULL, "_STA", "qv");
1928 tp_features.bay_status2 = bay2_handle &&
1929 acpi_evalf(bay2_handle, NULL, "_STA", "qv");
1930
1931 tp_features.bay_eject = bay_handle && bay_ej_handle &&
1932 (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
1933 tp_features.bay_eject2 = bay2_handle && bay2_ej_handle &&
1934 (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
1935
1936 vdbg_printk(TPACPI_DBG_INIT,
1937 "bay 1: status %s, eject %s; bay 2: status %s, eject %s\n",
1938 str_supported(tp_features.bay_status),
1939 str_supported(tp_features.bay_eject),
1940 str_supported(tp_features.bay_status2),
1941 str_supported(tp_features.bay_eject2));
1942
1943 return (tp_features.bay_status || tp_features.bay_eject ||
1944 tp_features.bay_status2 || tp_features.bay_eject2)? 0 : 1;
1945}
1946
1947static void bay_notify(struct ibm_struct *ibm, u32 event)
1948{
1949 acpi_bus_generate_event(ibm->acpi->device, event, 0);
1950}
1951
1952#define bay_occupied(b) (_sta(b##_handle) & 1)
1953
1954static int bay_read(char *p)
1955{
1956 int len = 0;
1957 int occupied = bay_occupied(bay);
1958 int occupied2 = bay_occupied(bay2);
1959 int eject, eject2;
1960
1961 len += sprintf(p + len, "status:\t\t%s\n",
1962 tp_features.bay_status ?
1963 (occupied ? "occupied" : "unoccupied") :
1964 "not supported");
1965 if (tp_features.bay_status2)
1966 len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
1967 "occupied" : "unoccupied");
1968
1969 eject = tp_features.bay_eject && occupied;
1970 eject2 = tp_features.bay_eject2 && occupied2;
1971
1972 if (eject && eject2)
1973 len += sprintf(p + len, "commands:\teject, eject2\n");
1974 else if (eject)
1975 len += sprintf(p + len, "commands:\teject\n");
1976 else if (eject2)
1977 len += sprintf(p + len, "commands:\teject2\n");
1978
1979 return len;
1980}
1981
1982static int bay_write(char *buf)
1983{
1984 char *cmd;
1985
1986 if (!tp_features.bay_eject && !tp_features.bay_eject2)
1987 return -ENODEV;
1988
1989 while ((cmd = next_cmd(&buf))) {
1990 if (tp_features.bay_eject && strlencmp(cmd, "eject") == 0) {
1991 if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
1992 return -EIO;
1993 } else if (tp_features.bay_eject2 &&
1994 strlencmp(cmd, "eject2") == 0) {
1995 if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
1996 return -EIO;
1997 } else
1998 return -EINVAL;
1999 }
2000
2001 return 0;
2002}
2003
2004static struct tp_acpi_drv_struct ibm_bay_acpidriver = {
2005 .notify = bay_notify,
2006 .handle = &bay_handle,
2007 .type = ACPI_SYSTEM_NOTIFY,
2008};
2009
2010static struct ibm_struct bay_driver_data = {
2011 .name = "bay",
2012 .read = bay_read,
2013 .write = bay_write,
2014 .acpi = &ibm_bay_acpidriver,
2015};
2016
2017#endif /* CONFIG_THINKPAD_ACPI_BAY */
2018
2019/*************************************************************************
2020 * CMOS subdriver
2021 */
2022
2023/* sysfs cmos_command -------------------------------------------------- */
2024static ssize_t cmos_command_store(struct device *dev,
2025 struct device_attribute *attr,
2026 const char *buf, size_t count)
2027{
2028 unsigned long cmos_cmd;
2029 int res;
2030
2031 if (parse_strtoul(buf, 21, &cmos_cmd))
2032 return -EINVAL;
2033
2034 res = issue_thinkpad_cmos_command(cmos_cmd);
2035 return (res)? res : count;
2036}
2037
2038static struct device_attribute dev_attr_cmos_command =
2039 __ATTR(cmos_command, S_IWUSR, NULL, cmos_command_store);
2040
2041/* --------------------------------------------------------------------- */
2042
2043static int __init cmos_init(struct ibm_init_struct *iibm)
2044{
2045 int res;
2046
2047 vdbg_printk(TPACPI_DBG_INIT,
2048 "initializing cmos commands subdriver\n");
2049
2050 IBM_ACPIHANDLE_INIT(cmos);
2051
2052 vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n",
2053 str_supported(cmos_handle != NULL));
2054
2055 res = device_create_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
2056 if (res)
2057 return res;
2058
2059 return (cmos_handle)? 0 : 1;
2060}
2061
2062static void cmos_exit(void)
2063{
2064 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
2065}
2066
2067static int cmos_read(char *p)
2068{
2069 int len = 0;
2070
2071 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
2072 R30, R31, T20-22, X20-21 */
2073 if (!cmos_handle)
2074 len += sprintf(p + len, "status:\t\tnot supported\n");
2075 else {
2076 len += sprintf(p + len, "status:\t\tsupported\n");
2077 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
2078 }
2079
2080 return len;
2081}
2082
2083static int cmos_write(char *buf)
2084{
2085 char *cmd;
2086 int cmos_cmd, res;
2087
2088 while ((cmd = next_cmd(&buf))) {
2089 if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
2090 cmos_cmd >= 0 && cmos_cmd <= 21) {
2091 /* cmos_cmd set */
2092 } else
2093 return -EINVAL;
2094
2095 res = issue_thinkpad_cmos_command(cmos_cmd);
2096 if (res)
2097 return res;
2098 }
2099
2100 return 0;
2101}
2102
2103static struct ibm_struct cmos_driver_data = {
2104 .name = "cmos",
2105 .read = cmos_read,
2106 .write = cmos_write,
2107 .exit = cmos_exit,
2108};
2109
2110/*************************************************************************
2111 * LED subdriver
2112 */
2113
2114static enum led_access_mode led_supported;
2115
2116IBM_HANDLE(led, ec, "SLED", /* 570 */
2117 "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
2118 "LED", /* all others */
2119 ); /* R30, R31 */
2120
2121static int __init led_init(struct ibm_init_struct *iibm)
2122{
2123 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
2124
2125 IBM_ACPIHANDLE_INIT(led);
2126
2127 if (!led_handle)
2128 /* led not supported on R30, R31 */
2129 led_supported = TPACPI_LED_NONE;
2130 else if (strlencmp(led_path, "SLED") == 0)
2131 /* 570 */
2132 led_supported = TPACPI_LED_570;
2133 else if (strlencmp(led_path, "SYSL") == 0)
2134 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
2135 led_supported = TPACPI_LED_OLD;
2136 else
2137 /* all others */
2138 led_supported = TPACPI_LED_NEW;
2139
2140 vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n",
2141 str_supported(led_supported), led_supported);
2142
2143 return (led_supported != TPACPI_LED_NONE)? 0 : 1;
2144}
2145
2146#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
2147
2148static int led_read(char *p)
2149{
2150 int len = 0;
2151
2152 if (!led_supported) {
2153 len += sprintf(p + len, "status:\t\tnot supported\n");
2154 return len;
2155 }
2156 len += sprintf(p + len, "status:\t\tsupported\n");
2157
2158 if (led_supported == TPACPI_LED_570) {
2159 /* 570 */
2160 int i, status;
2161 for (i = 0; i < 8; i++) {
2162 if (!acpi_evalf(ec_handle,
2163 &status, "GLED", "dd", 1 << i))
2164 return -EIO;
2165 len += sprintf(p + len, "%d:\t\t%s\n",
2166 i, led_status(status));
2167 }
2168 }
2169
2170 len += sprintf(p + len, "commands:\t"
2171 "<led> on, <led> off, <led> blink (<led> is 0-7)\n");
2172
2173 return len;
2174}
2175
2176/* off, on, blink */
2177static const int led_sled_arg1[] = { 0, 1, 3 };
2178static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
2179static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
2180static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
2181
2182static int led_write(char *buf)
2183{
2184 char *cmd;
2185 int led, ind, ret;
2186
2187 if (!led_supported)
2188 return -ENODEV;
2189
2190 while ((cmd = next_cmd(&buf))) {
2191 if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7)
2192 return -EINVAL;
2193
2194 if (strstr(cmd, "off")) {
2195 ind = 0;
2196 } else if (strstr(cmd, "on")) {
2197 ind = 1;
2198 } else if (strstr(cmd, "blink")) {
2199 ind = 2;
2200 } else
2201 return -EINVAL;
2202
2203 if (led_supported == TPACPI_LED_570) {
2204 /* 570 */
2205 led = 1 << led;
2206 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
2207 led, led_sled_arg1[ind]))
2208 return -EIO;
2209 } else if (led_supported == TPACPI_LED_OLD) {
2210 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
2211 led = 1 << led;
2212 ret = ec_write(TPACPI_LED_EC_HLMS, led);
2213 if (ret >= 0)
2214 ret =
2215 ec_write(TPACPI_LED_EC_HLBL,
2216 led * led_exp_hlbl[ind]);
2217 if (ret >= 0)
2218 ret =
2219 ec_write(TPACPI_LED_EC_HLCL,
2220 led * led_exp_hlcl[ind]);
2221 if (ret < 0)
2222 return ret;
2223 } else {
2224 /* all others */
2225 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
2226 led, led_led_arg1[ind]))
2227 return -EIO;
2228 }
2229 }
2230
2231 return 0;
2232}
2233
2234static struct ibm_struct led_driver_data = {
2235 .name = "led",
2236 .read = led_read,
2237 .write = led_write,
2238};
2239
2240/*************************************************************************
2241 * Beep subdriver
2242 */
2243
2244IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */
2245
2246static int __init beep_init(struct ibm_init_struct *iibm)
2247{
2248 vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n");
2249
2250 IBM_ACPIHANDLE_INIT(beep);
2251
2252 vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n",
2253 str_supported(beep_handle != NULL));
2254
2255 return (beep_handle)? 0 : 1;
2256}
2257
2258static int beep_read(char *p)
2259{
2260 int len = 0;
2261
2262 if (!beep_handle)
2263 len += sprintf(p + len, "status:\t\tnot supported\n");
2264 else {
2265 len += sprintf(p + len, "status:\t\tsupported\n");
2266 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
2267 }
2268
2269 return len;
2270}
2271
2272static int beep_write(char *buf)
2273{
2274 char *cmd;
2275 int beep_cmd;
2276
2277 if (!beep_handle)
2278 return -ENODEV;
2279
2280 while ((cmd = next_cmd(&buf))) {
2281 if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
2282 beep_cmd >= 0 && beep_cmd <= 17) {
2283 /* beep_cmd set */
2284 } else
2285 return -EINVAL;
2286 if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0))
2287 return -EIO;
2288 }
2289
2290 return 0;
2291}
2292
2293static struct ibm_struct beep_driver_data = {
2294 .name = "beep",
2295 .read = beep_read,
2296 .write = beep_write,
2297};
2298
2299/*************************************************************************
2300 * Thermal subdriver
2301 */
2302
2303static enum thermal_access_mode thermal_read_mode;
2304
2305/* sysfs temp##_input -------------------------------------------------- */
2306
2307static ssize_t thermal_temp_input_show(struct device *dev,
2308 struct device_attribute *attr,
2309 char *buf)
2310{
2311 struct sensor_device_attribute *sensor_attr =
2312 to_sensor_dev_attr(attr);
2313 int idx = sensor_attr->index;
2314 s32 value;
2315 int res;
2316
2317 res = thermal_get_sensor(idx, &value);
2318 if (res)
2319 return res;
2320 if (value == TP_EC_THERMAL_TMP_NA * 1000)
2321 return -ENXIO;
2322
2323 return snprintf(buf, PAGE_SIZE, "%d\n", value);
2324}
2325
2326#define THERMAL_SENSOR_ATTR_TEMP(_idxA, _idxB) \
2327 SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, thermal_temp_input_show, NULL, _idxB)
2328
2329static struct sensor_device_attribute sensor_dev_attr_thermal_temp_input[] = {
2330 THERMAL_SENSOR_ATTR_TEMP(1, 0),
2331 THERMAL_SENSOR_ATTR_TEMP(2, 1),
2332 THERMAL_SENSOR_ATTR_TEMP(3, 2),
2333 THERMAL_SENSOR_ATTR_TEMP(4, 3),
2334 THERMAL_SENSOR_ATTR_TEMP(5, 4),
2335 THERMAL_SENSOR_ATTR_TEMP(6, 5),
2336 THERMAL_SENSOR_ATTR_TEMP(7, 6),
2337 THERMAL_SENSOR_ATTR_TEMP(8, 7),
2338 THERMAL_SENSOR_ATTR_TEMP(9, 8),
2339 THERMAL_SENSOR_ATTR_TEMP(10, 9),
2340 THERMAL_SENSOR_ATTR_TEMP(11, 10),
2341 THERMAL_SENSOR_ATTR_TEMP(12, 11),
2342 THERMAL_SENSOR_ATTR_TEMP(13, 12),
2343 THERMAL_SENSOR_ATTR_TEMP(14, 13),
2344 THERMAL_SENSOR_ATTR_TEMP(15, 14),
2345 THERMAL_SENSOR_ATTR_TEMP(16, 15),
2346};
2347
2348#define THERMAL_ATTRS(X) \
2349 &sensor_dev_attr_thermal_temp_input[X].dev_attr.attr
2350
2351static struct attribute *thermal_temp_input_attr[] = {
2352 THERMAL_ATTRS(8),
2353 THERMAL_ATTRS(9),
2354 THERMAL_ATTRS(10),
2355 THERMAL_ATTRS(11),
2356 THERMAL_ATTRS(12),
2357 THERMAL_ATTRS(13),
2358 THERMAL_ATTRS(14),
2359 THERMAL_ATTRS(15),
2360 THERMAL_ATTRS(0),
2361 THERMAL_ATTRS(1),
2362 THERMAL_ATTRS(2),
2363 THERMAL_ATTRS(3),
2364 THERMAL_ATTRS(4),
2365 THERMAL_ATTRS(5),
2366 THERMAL_ATTRS(6),
2367 THERMAL_ATTRS(7),
2368 NULL
2369};
2370
2371static const struct attribute_group thermal_temp_input16_group = {
2372 .attrs = thermal_temp_input_attr
2373};
2374
2375static const struct attribute_group thermal_temp_input8_group = {
2376 .attrs = &thermal_temp_input_attr[8]
2377};
2378
2379#undef THERMAL_SENSOR_ATTR_TEMP
2380#undef THERMAL_ATTRS
2381
2382/* --------------------------------------------------------------------- */
2383
2384static int __init thermal_init(struct ibm_init_struct *iibm)
2385{
2386 u8 t, ta1, ta2;
2387 int i;
2388 int acpi_tmp7;
2389 int res;
2390
2391 vdbg_printk(TPACPI_DBG_INIT, "initializing thermal subdriver\n");
2392
2393 acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
2394
2395 if (ibm_thinkpad_ec_found && experimental) {
2396 /*
2397 * Direct EC access mode: sensors at registers
2398 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for
2399 * non-implemented, thermal sensors return 0x80 when
2400 * not available
2401 */
2402
2403 ta1 = ta2 = 0;
2404 for (i = 0; i < 8; i++) {
2405 if (acpi_ec_read(TP_EC_THERMAL_TMP0 + i, &t)) {
2406 ta1 |= t;
2407 } else {
2408 ta1 = 0;
2409 break;
2410 }
2411 if (acpi_ec_read(TP_EC_THERMAL_TMP8 + i, &t)) {
2412 ta2 |= t;
2413 } else {
2414 ta1 = 0;
2415 break;
2416 }
2417 }
2418 if (ta1 == 0) {
2419 /* This is sheer paranoia, but we handle it anyway */
2420 if (acpi_tmp7) {
2421 printk(IBM_ERR
2422 "ThinkPad ACPI EC access misbehaving, "
2423 "falling back to ACPI TMPx access mode\n");
2424 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
2425 } else {
2426 printk(IBM_ERR
2427 "ThinkPad ACPI EC access misbehaving, "
2428 "disabling thermal sensors access\n");
2429 thermal_read_mode = TPACPI_THERMAL_NONE;
2430 }
2431 } else {
2432 thermal_read_mode =
2433 (ta2 != 0) ?
2434 TPACPI_THERMAL_TPEC_16 : TPACPI_THERMAL_TPEC_8;
2435 }
2436 } else if (acpi_tmp7) {
2437 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
2438 /* 600e/x, 770e, 770x */
2439 thermal_read_mode = TPACPI_THERMAL_ACPI_UPDT;
2440 } else {
2441 /* Standard ACPI TMPx access, max 8 sensors */
2442 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
2443 }
2444 } else {
2445 /* temperatures not supported on 570, G4x, R30, R31, R32 */
2446 thermal_read_mode = TPACPI_THERMAL_NONE;
2447 }
2448
2449 vdbg_printk(TPACPI_DBG_INIT, "thermal is %s, mode %d\n",
2450 str_supported(thermal_read_mode != TPACPI_THERMAL_NONE),
2451 thermal_read_mode);
2452
2453 switch(thermal_read_mode) {
2454 case TPACPI_THERMAL_TPEC_16:
2455 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
2456 &thermal_temp_input16_group);
2457 if (res)
2458 return res;
2459 break;
2460 case TPACPI_THERMAL_TPEC_8:
2461 case TPACPI_THERMAL_ACPI_TMP07:
2462 case TPACPI_THERMAL_ACPI_UPDT:
2463 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
2464 &thermal_temp_input8_group);
2465 if (res)
2466 return res;
2467 break;
2468 case TPACPI_THERMAL_NONE:
2469 default:
2470 return 1;
2471 }
2472
2473 return 0;
2474}
2475
2476static void thermal_exit(void)
2477{
2478 switch(thermal_read_mode) {
2479 case TPACPI_THERMAL_TPEC_16:
2480 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
2481 &thermal_temp_input16_group);
2482 break;
2483 case TPACPI_THERMAL_TPEC_8:
2484 case TPACPI_THERMAL_ACPI_TMP07:
2485 case TPACPI_THERMAL_ACPI_UPDT:
2486 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
2487 &thermal_temp_input16_group);
2488 break;
2489 case TPACPI_THERMAL_NONE:
2490 default:
2491 break;
2492 }
2493}
2494
2495/* idx is zero-based */
2496static int thermal_get_sensor(int idx, s32 *value)
2497{
2498 int t;
2499 s8 tmp;
2500 char tmpi[5];
2501
2502 t = TP_EC_THERMAL_TMP0;
2503
2504 switch (thermal_read_mode) {
2505#if TPACPI_MAX_THERMAL_SENSORS >= 16
2506 case TPACPI_THERMAL_TPEC_16:
2507 if (idx >= 8 && idx <= 15) {
2508 t = TP_EC_THERMAL_TMP8;
2509 idx -= 8;
2510 }
2511 /* fallthrough */
2512#endif
2513 case TPACPI_THERMAL_TPEC_8:
2514 if (idx <= 7) {
2515 if (!acpi_ec_read(t + idx, &tmp))
2516 return -EIO;
2517 *value = tmp * 1000;
2518 return 0;
2519 }
2520 break;
2521
2522 case TPACPI_THERMAL_ACPI_UPDT:
2523 if (idx <= 7) {
2524 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
2525 if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
2526 return -EIO;
2527 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
2528 return -EIO;
2529 *value = (t - 2732) * 100;
2530 return 0;
2531 }
2532 break;
2533
2534 case TPACPI_THERMAL_ACPI_TMP07:
2535 if (idx <= 7) {
2536 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
2537 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
2538 return -EIO;
2539 *value = t * 1000;
2540 return 0;
2541 }
2542 break;
2543
2544 case TPACPI_THERMAL_NONE:
2545 default:
2546 return -ENOSYS;
2547 }
2548
2549 return -EINVAL;
2550}
2551
2552static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
2553{
2554 int res, i;
2555 int n;
2556
2557 n = 8;
2558 i = 0;
2559
2560 if (!s)
2561 return -EINVAL;
2562
2563 if (thermal_read_mode == TPACPI_THERMAL_TPEC_16)
2564 n = 16;
2565
2566 for(i = 0 ; i < n; i++) {
2567 res = thermal_get_sensor(i, &s->temp[i]);
2568 if (res)
2569 return res;
2570 }
2571
2572 return n;
2573}
2574
2575static int thermal_read(char *p)
2576{
2577 int len = 0;
2578 int n, i;
2579 struct ibm_thermal_sensors_struct t;
2580
2581 n = thermal_get_sensors(&t);
2582 if (unlikely(n < 0))
2583 return n;
2584
2585 len += sprintf(p + len, "temperatures:\t");
2586
2587 if (n > 0) {
2588 for (i = 0; i < (n - 1); i++)
2589 len += sprintf(p + len, "%d ", t.temp[i] / 1000);
2590 len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
2591 } else
2592 len += sprintf(p + len, "not supported\n");
2593
2594 return len;
2595}
2596
2597static struct ibm_struct thermal_driver_data = {
2598 .name = "thermal",
2599 .read = thermal_read,
2600 .exit = thermal_exit,
2601};
2602
2603/*************************************************************************
2604 * EC Dump subdriver
2605 */
2606
2607static u8 ecdump_regs[256];
2608
2609static int ecdump_read(char *p)
2610{
2611 int len = 0;
2612 int i, j;
2613 u8 v;
2614
2615 len += sprintf(p + len, "EC "
2616 " +00 +01 +02 +03 +04 +05 +06 +07"
2617 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
2618 for (i = 0; i < 256; i += 16) {
2619 len += sprintf(p + len, "EC 0x%02x:", i);
2620 for (j = 0; j < 16; j++) {
2621 if (!acpi_ec_read(i + j, &v))
2622 break;
2623 if (v != ecdump_regs[i + j])
2624 len += sprintf(p + len, " *%02x", v);
2625 else
2626 len += sprintf(p + len, " %02x", v);
2627 ecdump_regs[i + j] = v;
2628 }
2629 len += sprintf(p + len, "\n");
2630 if (j != 16)
2631 break;
2632 }
2633
2634 /* These are way too dangerous to advertise openly... */
2635#if 0
2636 len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
2637 " (<offset> is 00-ff, <value> is 00-ff)\n");
2638 len += sprintf(p + len, "commands:\t0x<offset> <value> "
2639 " (<offset> is 00-ff, <value> is 0-255)\n");
2640#endif
2641 return len;
2642}
2643
2644static int ecdump_write(char *buf)
2645{
2646 char *cmd;
2647 int i, v;
2648
2649 while ((cmd = next_cmd(&buf))) {
2650 if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
2651 /* i and v set */
2652 } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
2653 /* i and v set */
2654 } else
2655 return -EINVAL;
2656 if (i >= 0 && i < 256 && v >= 0 && v < 256) {
2657 if (!acpi_ec_write(i, v))
2658 return -EIO;
2659 } else
2660 return -EINVAL;
2661 }
2662
2663 return 0;
2664}
2665
2666static struct ibm_struct ecdump_driver_data = {
2667 .name = "ecdump",
2668 .read = ecdump_read,
2669 .write = ecdump_write,
2670 .flags.experimental = 1,
2671};
2672
2673/*************************************************************************
2674 * Backlight/brightness subdriver
2675 */
2676
2677static struct backlight_device *ibm_backlight_device = NULL;
2678
2679static struct backlight_ops ibm_backlight_data = {
2680 .get_brightness = brightness_get,
2681 .update_status = brightness_update_status,
2682};
2683
2684static int __init brightness_init(struct ibm_init_struct *iibm)
2685{
2686 int b;
2687
2688 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n");
2689
2690 b = brightness_get(NULL);
2691 if (b < 0)
2692 return b;
2693
2694 ibm_backlight_device = backlight_device_register(
2695 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
2696 &ibm_backlight_data);
2697 if (IS_ERR(ibm_backlight_device)) {
2698 printk(IBM_ERR "Could not register backlight device\n");
2699 return PTR_ERR(ibm_backlight_device);
2700 }
2701 vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n");
2702
2703 ibm_backlight_device->props.max_brightness = 7;
2704 ibm_backlight_device->props.brightness = b;
2705 backlight_update_status(ibm_backlight_device);
2706
2707 return 0;
2708}
2709
2710static void brightness_exit(void)
2711{
2712 if (ibm_backlight_device) {
2713 vdbg_printk(TPACPI_DBG_EXIT,
2714 "calling backlight_device_unregister()\n");
2715 backlight_device_unregister(ibm_backlight_device);
2716 ibm_backlight_device = NULL;
2717 }
2718}
2719
2720static int brightness_update_status(struct backlight_device *bd)
2721{
2722 return brightness_set(
2723 (bd->props.fb_blank == FB_BLANK_UNBLANK &&
2724 bd->props.power == FB_BLANK_UNBLANK) ?
2725 bd->props.brightness : 0);
2726}
2727
2728static int brightness_get(struct backlight_device *bd)
2729{
2730 u8 level;
2731 if (!acpi_ec_read(brightness_offset, &level))
2732 return -EIO;
2733
2734 level &= 0x7;
2735
2736 return level;
2737}
2738
2739static int brightness_set(int value)
2740{
2741 int cmos_cmd, inc, i;
2742 int current_value = brightness_get(NULL);
2743
2744 value &= 7;
2745
2746 cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN;
2747 inc = value > current_value ? 1 : -1;
2748 for (i = current_value; i != value; i += inc) {
2749 if (issue_thinkpad_cmos_command(cmos_cmd))
2750 return -EIO;
2751 if (!acpi_ec_write(brightness_offset, i + inc))
2752 return -EIO;
2753 }
2754
2755 return 0;
2756}
2757
2758static int brightness_read(char *p)
2759{
2760 int len = 0;
2761 int level;
2762
2763 if ((level = brightness_get(NULL)) < 0) {
2764 len += sprintf(p + len, "level:\t\tunreadable\n");
2765 } else {
2766 len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
2767 len += sprintf(p + len, "commands:\tup, down\n");
2768 len += sprintf(p + len, "commands:\tlevel <level>"
2769 " (<level> is 0-7)\n");
2770 }
2771
2772 return len;
2773}
2774
2775static int brightness_write(char *buf)
2776{
2777 int level;
2778 int new_level;
2779 char *cmd;
2780
2781 while ((cmd = next_cmd(&buf))) {
2782 if ((level = brightness_get(NULL)) < 0)
2783 return level;
2784 level &= 7;
2785
2786 if (strlencmp(cmd, "up") == 0) {
2787 new_level = level == 7 ? 7 : level + 1;
2788 } else if (strlencmp(cmd, "down") == 0) {
2789 new_level = level == 0 ? 0 : level - 1;
2790 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
2791 new_level >= 0 && new_level <= 7) {
2792 /* new_level set */
2793 } else
2794 return -EINVAL;
2795
2796 brightness_set(new_level);
2797 }
2798
2799 return 0;
2800}
2801
2802static struct ibm_struct brightness_driver_data = {
2803 .name = "brightness",
2804 .read = brightness_read,
2805 .write = brightness_write,
2806 .exit = brightness_exit,
2807};
2808
2809/*************************************************************************
2810 * Volume subdriver
2811 */
2812
2813static int volume_read(char *p)
2814{
2815 int len = 0;
2816 u8 level;
2817
2818 if (!acpi_ec_read(volume_offset, &level)) {
2819 len += sprintf(p + len, "level:\t\tunreadable\n");
2820 } else {
2821 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
2822 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
2823 len += sprintf(p + len, "commands:\tup, down, mute\n");
2824 len += sprintf(p + len, "commands:\tlevel <level>"
2825 " (<level> is 0-15)\n");
2826 }
2827
2828 return len;
2829}
2830
2831static int volume_write(char *buf)
2832{
2833 int cmos_cmd, inc, i;
2834 u8 level, mute;
2835 int new_level, new_mute;
2836 char *cmd;
2837
2838 while ((cmd = next_cmd(&buf))) {
2839 if (!acpi_ec_read(volume_offset, &level))
2840 return -EIO;
2841 new_mute = mute = level & 0x40;
2842 new_level = level = level & 0xf;
2843
2844 if (strlencmp(cmd, "up") == 0) {
2845 if (mute)
2846 new_mute = 0;
2847 else
2848 new_level = level == 15 ? 15 : level + 1;
2849 } else if (strlencmp(cmd, "down") == 0) {
2850 if (mute)
2851 new_mute = 0;
2852 else
2853 new_level = level == 0 ? 0 : level - 1;
2854 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
2855 new_level >= 0 && new_level <= 15) {
2856 /* new_level set */
2857 } else if (strlencmp(cmd, "mute") == 0) {
2858 new_mute = 0x40;
2859 } else
2860 return -EINVAL;
2861
2862 if (new_level != level) { /* mute doesn't change */
2863 cmos_cmd = new_level > level ? TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN;
2864 inc = new_level > level ? 1 : -1;
2865
2866 if (mute && (issue_thinkpad_cmos_command(cmos_cmd) ||
2867 !acpi_ec_write(volume_offset, level)))
2868 return -EIO;
2869
2870 for (i = level; i != new_level; i += inc)
2871 if (issue_thinkpad_cmos_command(cmos_cmd) ||
2872 !acpi_ec_write(volume_offset, i + inc))
2873 return -EIO;
2874
2875 if (mute && (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) ||
2876 !acpi_ec_write(volume_offset,
2877 new_level + mute)))
2878 return -EIO;
2879 }
2880
2881 if (new_mute != mute) { /* level doesn't change */
2882 cmos_cmd = new_mute ? TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP;
2883
2884 if (issue_thinkpad_cmos_command(cmos_cmd) ||
2885 !acpi_ec_write(volume_offset, level + new_mute))
2886 return -EIO;
2887 }
2888 }
2889
2890 return 0;
2891}
2892
2893static struct ibm_struct volume_driver_data = {
2894 .name = "volume",
2895 .read = volume_read,
2896 .write = volume_write,
2897};
2898
2899/*************************************************************************
2900 * Fan subdriver
2901 */
2902
2903/*
2904 * FAN ACCESS MODES
2905 *
2906 * TPACPI_FAN_RD_ACPI_GFAN:
2907 * ACPI GFAN method: returns fan level
2908 *
2909 * see TPACPI_FAN_WR_ACPI_SFAN
2910 * EC 0x2f (HFSP) not available if GFAN exists
2911 *
2912 * TPACPI_FAN_WR_ACPI_SFAN:
2913 * ACPI SFAN method: sets fan level, 0 (stop) to 7 (max)
2914 *
2915 * EC 0x2f (HFSP) might be available *for reading*, but do not use
2916 * it for writing.
2917 *
2918 * TPACPI_FAN_WR_TPEC:
2919 * ThinkPad EC register 0x2f (HFSP): fan control loop mode
2920 * Supported on almost all ThinkPads
2921 *
2922 * Fan speed changes of any sort (including those caused by the
2923 * disengaged mode) are usually done slowly by the firmware as the
2924 * maximum ammount of fan duty cycle change per second seems to be
2925 * limited.
2926 *
2927 * Reading is not available if GFAN exists.
2928 * Writing is not available if SFAN exists.
2929 *
2930 * Bits
2931 * 7 automatic mode engaged;
2932 * (default operation mode of the ThinkPad)
2933 * fan level is ignored in this mode.
2934 * 6 full speed mode (takes precedence over bit 7);
2935 * not available on all thinkpads. May disable
2936 * the tachometer while the fan controller ramps up
2937 * the speed (which can take up to a few *minutes*).
2938 * Speeds up fan to 100% duty-cycle, which is far above
2939 * the standard RPM levels. It is not impossible that
2940 * it could cause hardware damage.
2941 * 5-3 unused in some models. Extra bits for fan level
2942 * in others, but still useless as all values above
2943 * 7 map to the same speed as level 7 in these models.
2944 * 2-0 fan level (0..7 usually)
2945 * 0x00 = stop
2946 * 0x07 = max (set when temperatures critical)
2947 * Some ThinkPads may have other levels, see
2948 * TPACPI_FAN_WR_ACPI_FANS (X31/X40/X41)
2949 *
2950 * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at
2951 * boot. Apparently the EC does not intialize it, so unless ACPI DSDT
2952 * does so, its initial value is meaningless (0x07).
2953 *
2954 * For firmware bugs, refer to:
2955 * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
2956 *
2957 * ----
2958 *
2959 * ThinkPad EC register 0x84 (LSB), 0x85 (MSB):
2960 * Main fan tachometer reading (in RPM)
2961 *
2962 * This register is present on all ThinkPads with a new-style EC, and
2963 * it is known not to be present on the A21m/e, and T22, as there is
2964 * something else in offset 0x84 according to the ACPI DSDT. Other
2965 * ThinkPads from this same time period (and earlier) probably lack the
2966 * tachometer as well.
2967 *
2968 * Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare
2969 * was never fixed by IBM to report the EC firmware version string
2970 * probably support the tachometer (like the early X models), so
2971 * detecting it is quite hard. We need more data to know for sure.
2972 *
2973 * FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings
2974 * might result.
2975 *
2976 * FIRMWARE BUG: may go stale while the EC is switching to full speed
2977 * mode.
2978 *
2979 * For firmware bugs, refer to:
2980 * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
2981 *
2982 * TPACPI_FAN_WR_ACPI_FANS:
2983 * ThinkPad X31, X40, X41. Not available in the X60.
2984 *
2985 * FANS ACPI handle: takes three arguments: low speed, medium speed,
2986 * high speed. ACPI DSDT seems to map these three speeds to levels
2987 * as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH
2988 * (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3")
2989 *
2990 * The speeds are stored on handles
2991 * (FANA:FAN9), (FANC:FANB), (FANE:FAND).
2992 *
2993 * There are three default speed sets, acessible as handles:
2994 * FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
2995 *
2996 * ACPI DSDT switches which set is in use depending on various
2997 * factors.
2998 *
2999 * TPACPI_FAN_WR_TPEC is also available and should be used to
3000 * command the fan. The X31/X40/X41 seems to have 8 fan levels,
3001 * but the ACPI tables just mention level 7.
3002 */
3003
3004static enum fan_status_access_mode fan_status_access_mode;
3005static enum fan_control_access_mode fan_control_access_mode;
3006static enum fan_control_commands fan_control_commands;
3007
3008static u8 fan_control_initial_status;
3009static u8 fan_control_desired_level;
3010
3011static void fan_watchdog_fire(struct work_struct *ignored);
3012static int fan_watchdog_maxinterval;
3013static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
3014
3015IBM_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */
3016IBM_HANDLE(gfan, ec, "GFAN", /* 570 */
3017 "\\FSPD", /* 600e/x, 770e, 770x */
3018 ); /* all others */
3019IBM_HANDLE(sfan, ec, "SFAN", /* 570 */
3020 "JFNS", /* 770x-JL */
3021 ); /* all others */
3022
3023/*
3024 * SYSFS fan layout: hwmon compatible (device)
3025 *
3026 * pwm*_enable:
3027 * 0: "disengaged" mode
3028 * 1: manual mode
3029 * 2: native EC "auto" mode (recommended, hardware default)
3030 *
3031 * pwm*: set speed in manual mode, ignored otherwise.
3032 * 0 is level 0; 255 is level 7. Intermediate points done with linear
3033 * interpolation.
3034 *
3035 * fan*_input: tachometer reading, RPM
3036 *
3037 *
3038 * SYSFS fan layout: extensions
3039 *
3040 * fan_watchdog (driver):
3041 * fan watchdog interval in seconds, 0 disables (default), max 120
3042 */
3043
3044/* sysfs fan pwm1_enable ----------------------------------------------- */
3045static ssize_t fan_pwm1_enable_show(struct device *dev,
3046 struct device_attribute *attr,
3047 char *buf)
3048{
3049 int res, mode;
3050 u8 status;
3051
3052 res = fan_get_status_safe(&status);
3053 if (res)
3054 return res;
3055
3056 if (unlikely(tp_features.fan_ctrl_status_undef)) {
3057 if (status != fan_control_initial_status) {
3058 tp_features.fan_ctrl_status_undef = 0;
3059 } else {
3060 /* Return most likely status. In fact, it
3061 * might be the only possible status */
3062 status = TP_EC_FAN_AUTO;
3063 }
3064 }
3065
3066 if (status & TP_EC_FAN_FULLSPEED) {
3067 mode = 0;
3068 } else if (status & TP_EC_FAN_AUTO) {
3069 mode = 2;
3070 } else
3071 mode = 1;
3072
3073 return snprintf(buf, PAGE_SIZE, "%d\n", mode);
3074}
3075
3076static ssize_t fan_pwm1_enable_store(struct device *dev,
3077 struct device_attribute *attr,
3078 const char *buf, size_t count)
3079{
3080 unsigned long t;
3081 int res, level;
3082
3083 if (parse_strtoul(buf, 2, &t))
3084 return -EINVAL;
3085
3086 switch (t) {
3087 case 0:
3088 level = TP_EC_FAN_FULLSPEED;
3089 break;
3090 case 1:
3091 level = TPACPI_FAN_LAST_LEVEL;
3092 break;
3093 case 2:
3094 level = TP_EC_FAN_AUTO;
3095 break;
3096 case 3:
3097 /* reserved for software-controlled auto mode */
3098 return -ENOSYS;
3099 default:
3100 return -EINVAL;
3101 }
3102
3103 res = fan_set_level_safe(level);
3104 if (res == -ENXIO)
3105 return -EINVAL;
3106 else if (res < 0)
3107 return res;
3108
3109 fan_watchdog_reset();
3110
3111 return count;
3112}
3113
3114static struct device_attribute dev_attr_fan_pwm1_enable =
3115 __ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
3116 fan_pwm1_enable_show, fan_pwm1_enable_store);
3117
3118/* sysfs fan pwm1 ------------------------------------------------------ */
3119static ssize_t fan_pwm1_show(struct device *dev,
3120 struct device_attribute *attr,
3121 char *buf)
3122{
3123 int res;
3124 u8 status;
3125
3126 res = fan_get_status_safe(&status);
3127 if (res)
3128 return res;
3129
3130 if (unlikely(tp_features.fan_ctrl_status_undef)) {
3131 if (status != fan_control_initial_status) {
3132 tp_features.fan_ctrl_status_undef = 0;
3133 } else {
3134 status = TP_EC_FAN_AUTO;
3135 }
3136 }
3137
3138 if ((status &
3139 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0)
3140 status = fan_control_desired_level;
3141
3142 if (status > 7)
3143 status = 7;
3144
3145 return snprintf(buf, PAGE_SIZE, "%u\n", (status * 255) / 7);
3146}
3147
3148static ssize_t fan_pwm1_store(struct device *dev,
3149 struct device_attribute *attr,
3150 const char *buf, size_t count)
3151{
3152 unsigned long s;
3153 int rc;
3154 u8 status, newlevel;
3155
3156 if (parse_strtoul(buf, 255, &s))
3157 return -EINVAL;
3158
3159 /* scale down from 0-255 to 0-7 */
3160 newlevel = (s >> 5) & 0x07;
3161
3162 rc = mutex_lock_interruptible(&fan_mutex);
3163 if (rc < 0)
3164 return rc;
3165
3166 rc = fan_get_status(&status);
3167 if (!rc && (status &
3168 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
3169 rc = fan_set_level(newlevel);
3170 if (rc == -ENXIO)
3171 rc = -EINVAL;
3172 else if (!rc) {
3173 fan_update_desired_level(newlevel);
3174 fan_watchdog_reset();
3175 }
3176 }
3177
3178 mutex_unlock(&fan_mutex);
3179 return (rc)? rc : count;
3180}
3181
3182static struct device_attribute dev_attr_fan_pwm1 =
3183 __ATTR(pwm1, S_IWUSR | S_IRUGO,
3184 fan_pwm1_show, fan_pwm1_store);
3185
3186/* sysfs fan fan1_input ------------------------------------------------ */
3187static ssize_t fan_fan1_input_show(struct device *dev,
3188 struct device_attribute *attr,
3189 char *buf)
3190{
3191 int res;
3192 unsigned int speed;
3193
3194 res = fan_get_speed(&speed);
3195 if (res < 0)
3196 return res;
3197
3198 return snprintf(buf, PAGE_SIZE, "%u\n", speed);
3199}
3200
3201static struct device_attribute dev_attr_fan_fan1_input =
3202 __ATTR(fan1_input, S_IRUGO,
3203 fan_fan1_input_show, NULL);
3204
3205/* sysfs fan fan_watchdog (driver) ------------------------------------- */
3206static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
3207 char *buf)
3208{
3209 return snprintf(buf, PAGE_SIZE, "%u\n", fan_watchdog_maxinterval);
3210}
3211
3212static ssize_t fan_fan_watchdog_store(struct device_driver *drv,
3213 const char *buf, size_t count)
3214{
3215 unsigned long t;
3216
3217 if (parse_strtoul(buf, 120, &t))
3218 return -EINVAL;
3219
3220 if (!fan_control_allowed)
3221 return -EPERM;
3222
3223 fan_watchdog_maxinterval = t;
3224 fan_watchdog_reset();
3225
3226 return count;
3227}
3228
3229static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO,
3230 fan_fan_watchdog_show, fan_fan_watchdog_store);
3231
3232/* --------------------------------------------------------------------- */
3233static struct attribute *fan_attributes[] = {
3234 &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr,
3235 &dev_attr_fan_fan1_input.attr,
3236 NULL
3237};
3238
3239static const struct attribute_group fan_attr_group = {
3240 .attrs = fan_attributes,
3241};
3242
3243static int __init fan_init(struct ibm_init_struct *iibm)
3244{
3245 int rc;
3246
3247 vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n");
3248
3249 mutex_init(&fan_mutex);
3250 fan_status_access_mode = TPACPI_FAN_NONE;
3251 fan_control_access_mode = TPACPI_FAN_WR_NONE;
3252 fan_control_commands = 0;
3253 fan_watchdog_maxinterval = 0;
3254 tp_features.fan_ctrl_status_undef = 0;
3255 fan_control_desired_level = 7;
3256
3257 IBM_ACPIHANDLE_INIT(fans);
3258 IBM_ACPIHANDLE_INIT(gfan);
3259 IBM_ACPIHANDLE_INIT(sfan);
3260
3261 if (gfan_handle) {
3262 /* 570, 600e/x, 770e, 770x */
3263 fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
3264 } else {
3265 /* all other ThinkPads: note that even old-style
3266 * ThinkPad ECs supports the fan control register */
3267 if (likely(acpi_ec_read(fan_status_offset,
3268 &fan_control_initial_status))) {
3269 fan_status_access_mode = TPACPI_FAN_RD_TPEC;
3270
3271 /* In some ThinkPads, neither the EC nor the ACPI
3272 * DSDT initialize the fan status, and it ends up
3273 * being set to 0x07 when it *could* be either
3274 * 0x07 or 0x80.
3275 *
3276 * Enable for TP-1Y (T43), TP-78 (R51e),
3277 * TP-76 (R52), TP-70 (T43, R52), which are known
3278 * to be buggy. */
3279 if (fan_control_initial_status == 0x07 &&
3280 ibm_thinkpad_ec_found &&
3281 ((ibm_thinkpad_ec_found[0] == '1' &&
3282 ibm_thinkpad_ec_found[1] == 'Y') ||
3283 (ibm_thinkpad_ec_found[0] == '7' &&
3284 (ibm_thinkpad_ec_found[1] == '6' ||
3285 ibm_thinkpad_ec_found[1] == '8' ||
3286 ibm_thinkpad_ec_found[1] == '0'))
3287 )) {
3288 printk(IBM_NOTICE
3289 "fan_init: initial fan status is "
3290 "unknown, assuming it is in auto "
3291 "mode\n");
3292 tp_features.fan_ctrl_status_undef = 1;
3293 }
3294 } else {
3295 printk(IBM_ERR
3296 "ThinkPad ACPI EC access misbehaving, "
3297 "fan status and control unavailable\n");
3298 return 1;
3299 }
3300 }
3301
3302 if (sfan_handle) {
3303 /* 570, 770x-JL */
3304 fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN;
3305 fan_control_commands |=
3306 TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_ENABLE;
3307 } else {
3308 if (!gfan_handle) {
3309 /* gfan without sfan means no fan control */
3310 /* all other models implement TP EC 0x2f control */
3311
3312 if (fans_handle) {
3313 /* X31, X40, X41 */
3314 fan_control_access_mode =
3315 TPACPI_FAN_WR_ACPI_FANS;
3316 fan_control_commands |=
3317 TPACPI_FAN_CMD_SPEED |
3318 TPACPI_FAN_CMD_LEVEL |
3319 TPACPI_FAN_CMD_ENABLE;
3320 } else {
3321 fan_control_access_mode = TPACPI_FAN_WR_TPEC;
3322 fan_control_commands |=
3323 TPACPI_FAN_CMD_LEVEL |
3324 TPACPI_FAN_CMD_ENABLE;
3325 }
3326 }
3327 }
3328
3329 vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n",
3330 str_supported(fan_status_access_mode != TPACPI_FAN_NONE ||
3331 fan_control_access_mode != TPACPI_FAN_WR_NONE),
3332 fan_status_access_mode, fan_control_access_mode);
3333
3334 /* fan control master switch */
3335 if (!fan_control_allowed) {
3336 fan_control_access_mode = TPACPI_FAN_WR_NONE;
3337 fan_control_commands = 0;
3338 dbg_printk(TPACPI_DBG_INIT,
3339 "fan control features disabled by parameter\n");
3340 }
3341
3342 /* update fan_control_desired_level */
3343 if (fan_status_access_mode != TPACPI_FAN_NONE)
3344 fan_get_status_safe(NULL);
3345
3346 if (fan_status_access_mode != TPACPI_FAN_NONE ||
3347 fan_control_access_mode != TPACPI_FAN_WR_NONE) {
3348 rc = sysfs_create_group(&tpacpi_pdev->dev.kobj,
3349 &fan_attr_group);
3350 if (!(rc < 0))
3351 rc = driver_create_file(&tpacpi_pdriver.driver,
3352 &driver_attr_fan_watchdog);
3353 if (rc < 0)
3354 return rc;
3355 return 0;
3356 } else
3357 return 1;
3358}
3359
3360/*
3361 * Call with fan_mutex held
3362 */
3363static void fan_update_desired_level(u8 status)
3364{
3365 if ((status &
3366 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
3367 if (status > 7)
3368 fan_control_desired_level = 7;
3369 else
3370 fan_control_desired_level = status;
3371 }
3372}
3373
3374static int fan_get_status(u8 *status)
3375{
3376 u8 s;
3377
3378 /* TODO:
3379 * Add TPACPI_FAN_RD_ACPI_FANS ? */
3380
3381 switch (fan_status_access_mode) {
3382 case TPACPI_FAN_RD_ACPI_GFAN:
3383 /* 570, 600e/x, 770e, 770x */
3384
3385 if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
3386 return -EIO;
3387
3388 if (likely(status))
3389 *status = s & 0x07;
3390
3391 break;
3392
3393 case TPACPI_FAN_RD_TPEC:
3394 /* all except 570, 600e/x, 770e, 770x */
3395 if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
3396 return -EIO;
3397
3398 if (likely(status))
3399 *status = s;
3400
3401 break;
3402
3403 default:
3404 return -ENXIO;
3405 }
3406
3407 return 0;
3408}
3409
3410static int fan_get_status_safe(u8 *status)
3411{
3412 int rc;
3413 u8 s;
3414
3415 rc = mutex_lock_interruptible(&fan_mutex);
3416 if (rc < 0)
3417 return rc;
3418 rc = fan_get_status(&s);
3419 if (!rc)
3420 fan_update_desired_level(s);
3421 mutex_unlock(&fan_mutex);
3422
3423 if (status)
3424 *status = s;
3425
3426 return rc;
3427}
3428
3429static void fan_exit(void)
3430{
3431 vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n");
3432
3433 /* FIXME: can we really do this unconditionally? */
3434 sysfs_remove_group(&tpacpi_pdev->dev.kobj, &fan_attr_group);
3435 driver_remove_file(&tpacpi_pdriver.driver, &driver_attr_fan_watchdog);
3436
3437 cancel_delayed_work(&fan_watchdog_task);
3438 flush_scheduled_work();
3439}
3440
3441static int fan_get_speed(unsigned int *speed)
3442{
3443 u8 hi, lo;
3444
3445 switch (fan_status_access_mode) {
3446 case TPACPI_FAN_RD_TPEC:
3447 /* all except 570, 600e/x, 770e, 770x */
3448 if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
3449 !acpi_ec_read(fan_rpm_offset + 1, &hi)))
3450 return -EIO;
3451
3452 if (likely(speed))
3453 *speed = (hi << 8) | lo;
3454
3455 break;
3456
3457 default:
3458 return -ENXIO;
3459 }
3460
3461 return 0;
3462}
3463
3464static void fan_watchdog_fire(struct work_struct *ignored)
3465{
3466 int rc;
3467
3468 printk(IBM_NOTICE "fan watchdog: enabling fan\n");
3469 rc = fan_set_enable();
3470 if (rc < 0) {
3471 printk(IBM_ERR "fan watchdog: error %d while enabling fan, "
3472 "will try again later...\n", -rc);
3473 /* reschedule for later */
3474 fan_watchdog_reset();
3475 }
3476}
3477
3478static void fan_watchdog_reset(void)
3479{
3480 static int fan_watchdog_active = 0;
3481
3482 if (fan_control_access_mode == TPACPI_FAN_WR_NONE)
3483 return;
3484
3485 if (fan_watchdog_active)
3486 cancel_delayed_work(&fan_watchdog_task);
3487
3488 if (fan_watchdog_maxinterval > 0) {
3489 fan_watchdog_active = 1;
3490 if (!schedule_delayed_work(&fan_watchdog_task,
3491 msecs_to_jiffies(fan_watchdog_maxinterval
3492 * 1000))) {
3493 printk(IBM_ERR "failed to schedule the fan watchdog, "
3494 "watchdog will not trigger\n");
3495 }
3496 } else
3497 fan_watchdog_active = 0;
3498}
3499
3500static int fan_set_level(int level)
3501{
3502 if (!fan_control_allowed)
3503 return -EPERM;
3504
3505 switch (fan_control_access_mode) {
3506 case TPACPI_FAN_WR_ACPI_SFAN:
3507 if (level >= 0 && level <= 7) {
3508 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
3509 return -EIO;
3510 } else
3511 return -EINVAL;
3512 break;
3513
3514 case TPACPI_FAN_WR_ACPI_FANS:
3515 case TPACPI_FAN_WR_TPEC:
3516 if ((level != TP_EC_FAN_AUTO) &&
3517 (level != TP_EC_FAN_FULLSPEED) &&
3518 ((level < 0) || (level > 7)))
3519 return -EINVAL;
3520
3521 /* safety net should the EC not support AUTO
3522 * or FULLSPEED mode bits and just ignore them */
3523 if (level & TP_EC_FAN_FULLSPEED)
3524 level |= 7; /* safety min speed 7 */
3525 else if (level & TP_EC_FAN_FULLSPEED)
3526 level |= 4; /* safety min speed 4 */
3527
3528 if (!acpi_ec_write(fan_status_offset, level))
3529 return -EIO;
3530 else
3531 tp_features.fan_ctrl_status_undef = 0;
3532 break;
3533
3534 default:
3535 return -ENXIO;
3536 }
3537 return 0;
3538}
3539
3540static int fan_set_level_safe(int level)
3541{
3542 int rc;
3543
3544 if (!fan_control_allowed)
3545 return -EPERM;
3546
3547 rc = mutex_lock_interruptible(&fan_mutex);
3548 if (rc < 0)
3549 return rc;
3550
3551 if (level == TPACPI_FAN_LAST_LEVEL)
3552 level = fan_control_desired_level;
3553
3554 rc = fan_set_level(level);
3555 if (!rc)
3556 fan_update_desired_level(level);
3557
3558 mutex_unlock(&fan_mutex);
3559 return rc;
3560}
3561
3562static int fan_set_enable(void)
3563{
3564 u8 s;
3565 int rc;
3566
3567 if (!fan_control_allowed)
3568 return -EPERM;
3569
3570 rc = mutex_lock_interruptible(&fan_mutex);
3571 if (rc < 0)
3572 return rc;
3573
3574 switch (fan_control_access_mode) {
3575 case TPACPI_FAN_WR_ACPI_FANS:
3576 case TPACPI_FAN_WR_TPEC:
3577 rc = fan_get_status(&s);
3578 if (rc < 0)
3579 break;
3580
3581 /* Don't go out of emergency fan mode */
3582 if (s != 7) {
3583 s &= 0x07;
3584 s |= TP_EC_FAN_AUTO | 4; /* min fan speed 4 */
3585 }
3586
3587 if (!acpi_ec_write(fan_status_offset, s))
3588 rc = -EIO;
3589 else {
3590 tp_features.fan_ctrl_status_undef = 0;
3591 rc = 0;
3592 }
3593 break;
3594
3595 case TPACPI_FAN_WR_ACPI_SFAN:
3596 rc = fan_get_status(&s);
3597 if (rc < 0)
3598 break;
3599
3600 s &= 0x07;
3601
3602 /* Set fan to at least level 4 */
3603 s |= 4;
3604
3605 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
3606 rc= -EIO;
3607 else
3608 rc = 0;
3609 break;
3610
3611 default:
3612 rc = -ENXIO;
3613 }
3614
3615 mutex_unlock(&fan_mutex);
3616 return rc;
3617}
3618
3619static int fan_set_disable(void)
3620{
3621 int rc;
3622
3623 if (!fan_control_allowed)
3624 return -EPERM;
3625
3626 rc = mutex_lock_interruptible(&fan_mutex);
3627 if (rc < 0)
3628 return rc;
3629
3630 rc = 0;
3631 switch (fan_control_access_mode) {
3632 case TPACPI_FAN_WR_ACPI_FANS:
3633 case TPACPI_FAN_WR_TPEC:
3634 if (!acpi_ec_write(fan_status_offset, 0x00))
3635 rc = -EIO;
3636 else {
3637 fan_control_desired_level = 0;
3638 tp_features.fan_ctrl_status_undef = 0;
3639 }
3640 break;
3641
3642 case TPACPI_FAN_WR_ACPI_SFAN:
3643 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
3644 rc = -EIO;
3645 else
3646 fan_control_desired_level = 0;
3647 break;
3648
3649 default:
3650 rc = -ENXIO;
3651 }
3652
3653
3654 mutex_unlock(&fan_mutex);
3655 return rc;
3656}
3657
3658static int fan_set_speed(int speed)
3659{
3660 int rc;
3661
3662 if (!fan_control_allowed)
3663 return -EPERM;
3664
3665 rc = mutex_lock_interruptible(&fan_mutex);
3666 if (rc < 0)
3667 return rc;
3668
3669 rc = 0;
3670 switch (fan_control_access_mode) {
3671 case TPACPI_FAN_WR_ACPI_FANS:
3672 if (speed >= 0 && speed <= 65535) {
3673 if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
3674 speed, speed, speed))
3675 rc = -EIO;
3676 } else
3677 rc = -EINVAL;
3678 break;
3679
3680 default:
3681 rc = -ENXIO;
3682 }
3683
3684 mutex_unlock(&fan_mutex);
3685 return rc;
3686}
3687
3688static int fan_read(char *p)
3689{
3690 int len = 0;
3691 int rc;
3692 u8 status;
3693 unsigned int speed = 0;
3694
3695 switch (fan_status_access_mode) {
3696 case TPACPI_FAN_RD_ACPI_GFAN:
3697 /* 570, 600e/x, 770e, 770x */
3698 if ((rc = fan_get_status_safe(&status)) < 0)
3699 return rc;
3700
3701 len += sprintf(p + len, "status:\t\t%s\n"
3702 "level:\t\t%d\n",
3703 (status != 0) ? "enabled" : "disabled", status);
3704 break;
3705
3706 case TPACPI_FAN_RD_TPEC:
3707 /* all except 570, 600e/x, 770e, 770x */
3708 if ((rc = fan_get_status_safe(&status)) < 0)
3709 return rc;
3710
3711 if (unlikely(tp_features.fan_ctrl_status_undef)) {
3712 if (status != fan_control_initial_status)
3713 tp_features.fan_ctrl_status_undef = 0;
3714 else
3715 /* Return most likely status. In fact, it
3716 * might be the only possible status */
3717 status = TP_EC_FAN_AUTO;
3718 }
3719
3720 len += sprintf(p + len, "status:\t\t%s\n",
3721 (status != 0) ? "enabled" : "disabled");
3722
3723 if ((rc = fan_get_speed(&speed)) < 0)
3724 return rc;
3725
3726 len += sprintf(p + len, "speed:\t\t%d\n", speed);
3727
3728 if (status & TP_EC_FAN_FULLSPEED)
3729 /* Disengaged mode takes precedence */
3730 len += sprintf(p + len, "level:\t\tdisengaged\n");
3731 else if (status & TP_EC_FAN_AUTO)
3732 len += sprintf(p + len, "level:\t\tauto\n");
3733 else
3734 len += sprintf(p + len, "level:\t\t%d\n", status);
3735 break;
3736
3737 case TPACPI_FAN_NONE:
3738 default:
3739 len += sprintf(p + len, "status:\t\tnot supported\n");
3740 }
3741
3742 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
3743 len += sprintf(p + len, "commands:\tlevel <level>");
3744
3745 switch (fan_control_access_mode) {
3746 case TPACPI_FAN_WR_ACPI_SFAN:
3747 len += sprintf(p + len, " (<level> is 0-7)\n");
3748 break;
3749
3750 default:
3751 len += sprintf(p + len, " (<level> is 0-7, "
3752 "auto, disengaged, full-speed)\n");
3753 break;
3754 }
3755 }
3756
3757 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
3758 len += sprintf(p + len, "commands:\tenable, disable\n"
3759 "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
3760 "1-120 (seconds))\n");
3761
3762 if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
3763 len += sprintf(p + len, "commands:\tspeed <speed>"
3764 " (<speed> is 0-65535)\n");
3765
3766 return len;
3767}
3768
3769static int fan_write_cmd_level(const char *cmd, int *rc)
3770{
3771 int level;
3772
3773 if (strlencmp(cmd, "level auto") == 0)
3774 level = TP_EC_FAN_AUTO;
3775 else if ((strlencmp(cmd, "level disengaged") == 0) |
3776 (strlencmp(cmd, "level full-speed") == 0))
3777 level = TP_EC_FAN_FULLSPEED;
3778 else if (sscanf(cmd, "level %d", &level) != 1)
3779 return 0;
3780
3781 if ((*rc = fan_set_level_safe(level)) == -ENXIO)
3782 printk(IBM_ERR "level command accepted for unsupported "
3783 "access mode %d", fan_control_access_mode);
3784
3785 return 1;
3786}
3787
3788static int fan_write_cmd_enable(const char *cmd, int *rc)
3789{
3790 if (strlencmp(cmd, "enable") != 0)
3791 return 0;
3792
3793 if ((*rc = fan_set_enable()) == -ENXIO)
3794 printk(IBM_ERR "enable command accepted for unsupported "
3795 "access mode %d", fan_control_access_mode);
3796
3797 return 1;
3798}
3799
3800static int fan_write_cmd_disable(const char *cmd, int *rc)
3801{
3802 if (strlencmp(cmd, "disable") != 0)
3803 return 0;
3804
3805 if ((*rc = fan_set_disable()) == -ENXIO)
3806 printk(IBM_ERR "disable command accepted for unsupported "
3807 "access mode %d", fan_control_access_mode);
3808
3809 return 1;
3810}
3811
3812static int fan_write_cmd_speed(const char *cmd, int *rc)
3813{
3814 int speed;
3815
3816 /* TODO:
3817 * Support speed <low> <medium> <high> ? */
3818
3819 if (sscanf(cmd, "speed %d", &speed) != 1)
3820 return 0;
3821
3822 if ((*rc = fan_set_speed(speed)) == -ENXIO)
3823 printk(IBM_ERR "speed command accepted for unsupported "
3824 "access mode %d", fan_control_access_mode);
3825
3826 return 1;
3827}
3828
3829static int fan_write_cmd_watchdog(const char *cmd, int *rc)
3830{
3831 int interval;
3832
3833 if (sscanf(cmd, "watchdog %d", &interval) != 1)
3834 return 0;
3835
3836 if (interval < 0 || interval > 120)
3837 *rc = -EINVAL;
3838 else
3839 fan_watchdog_maxinterval = interval;
3840
3841 return 1;
3842}
3843
3844static int fan_write(char *buf)
3845{
3846 char *cmd;
3847 int rc = 0;
3848
3849 while (!rc && (cmd = next_cmd(&buf))) {
3850 if (!((fan_control_commands & TPACPI_FAN_CMD_LEVEL) &&
3851 fan_write_cmd_level(cmd, &rc)) &&
3852 !((fan_control_commands & TPACPI_FAN_CMD_ENABLE) &&
3853 (fan_write_cmd_enable(cmd, &rc) ||
3854 fan_write_cmd_disable(cmd, &rc) ||
3855 fan_write_cmd_watchdog(cmd, &rc))) &&
3856 !((fan_control_commands & TPACPI_FAN_CMD_SPEED) &&
3857 fan_write_cmd_speed(cmd, &rc))
3858 )
3859 rc = -EINVAL;
3860 else if (!rc)
3861 fan_watchdog_reset();
3862 }
3863
3864 return rc;
3865}
3866
3867static struct ibm_struct fan_driver_data = {
3868 .name = "fan",
3869 .read = fan_read,
3870 .write = fan_write,
3871 .exit = fan_exit,
3872};
3873
3874/****************************************************************************
3875 ****************************************************************************
3876 *
3877 * Infrastructure
3878 *
3879 ****************************************************************************
3880 ****************************************************************************/
3881
3882/* /proc support */
3883static struct proc_dir_entry *proc_dir = NULL;
3884
3885/* Subdriver registry */
3886static LIST_HEAD(tpacpi_all_drivers);
3887
3888
3889/*
3890 * Module and infrastructure proble, init and exit handling
3891 */
3892
3893#ifdef CONFIG_THINKPAD_ACPI_DEBUG
3894static const char * __init str_supported(int is_supported)
3895{
3896 static char text_unsupported[] __initdata = "not supported";
3897
3898 return (is_supported)? &text_unsupported[4] : &text_unsupported[0];
3899}
3900#endif /* CONFIG_THINKPAD_ACPI_DEBUG */
3901
3902static int __init ibm_init(struct ibm_init_struct *iibm)
3903{
3904 int ret;
3905 struct ibm_struct *ibm = iibm->data;
3906 struct proc_dir_entry *entry;
3907
3908 BUG_ON(ibm == NULL);
3909
3910 INIT_LIST_HEAD(&ibm->all_drivers);
3911
3912 if (ibm->flags.experimental && !experimental)
3913 return 0;
3914
3915 dbg_printk(TPACPI_DBG_INIT,
3916 "probing for %s\n", ibm->name);
3917
3918 if (iibm->init) {
3919 ret = iibm->init(iibm);
3920 if (ret > 0)
3921 return 0; /* probe failed */
3922 if (ret)
3923 return ret;
3924
3925 ibm->flags.init_called = 1;
3926 }
3927
3928 if (ibm->acpi) {
3929 if (ibm->acpi->hid) {
3930 ret = register_tpacpi_subdriver(ibm);
3931 if (ret)
3932 goto err_out;
3933 }
3934
3935 if (ibm->acpi->notify) {
3936 ret = setup_acpi_notify(ibm);
3937 if (ret == -ENODEV) {
3938 printk(IBM_NOTICE "disabling subdriver %s\n",
3939 ibm->name);
3940 ret = 0;
3941 goto err_out;
3942 }
3943 if (ret < 0)
3944 goto err_out;
3945 }
3946 }
3947
3948 dbg_printk(TPACPI_DBG_INIT,
3949 "%s installed\n", ibm->name);
3950
3951 if (ibm->read) {
3952 entry = create_proc_entry(ibm->name,
3953 S_IFREG | S_IRUGO | S_IWUSR,
3954 proc_dir);
3955 if (!entry) {
3956 printk(IBM_ERR "unable to create proc entry %s\n",
3957 ibm->name);
3958 ret = -ENODEV;
3959 goto err_out;
3960 }
3961 entry->owner = THIS_MODULE;
3962 entry->data = ibm;
3963 entry->read_proc = &dispatch_procfs_read;
3964 if (ibm->write)
3965 entry->write_proc = &dispatch_procfs_write;
3966 ibm->flags.proc_created = 1;
3967 }
3968
3969 list_add_tail(&ibm->all_drivers, &tpacpi_all_drivers);
3970
3971 return 0;
3972
3973err_out:
3974 dbg_printk(TPACPI_DBG_INIT,
3975 "%s: at error exit path with result %d\n",
3976 ibm->name, ret);
3977
3978 ibm_exit(ibm);
3979 return (ret < 0)? ret : 0;
3980}
3981
3982static void ibm_exit(struct ibm_struct *ibm)
3983{
3984 dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name);
3985
3986 list_del_init(&ibm->all_drivers);
3987
3988 if (ibm->flags.acpi_notify_installed) {
3989 dbg_printk(TPACPI_DBG_EXIT,
3990 "%s: acpi_remove_notify_handler\n", ibm->name);
3991 BUG_ON(!ibm->acpi);
3992 acpi_remove_notify_handler(*ibm->acpi->handle,
3993 ibm->acpi->type,
3994 dispatch_acpi_notify);
3995 ibm->flags.acpi_notify_installed = 0;
3996 ibm->flags.acpi_notify_installed = 0;
3997 }
3998
3999 if (ibm->flags.proc_created) {
4000 dbg_printk(TPACPI_DBG_EXIT,
4001 "%s: remove_proc_entry\n", ibm->name);
4002 remove_proc_entry(ibm->name, proc_dir);
4003 ibm->flags.proc_created = 0;
4004 }
4005
4006 if (ibm->flags.acpi_driver_registered) {
4007 dbg_printk(TPACPI_DBG_EXIT,
4008 "%s: acpi_bus_unregister_driver\n", ibm->name);
4009 BUG_ON(!ibm->acpi);
4010 acpi_bus_unregister_driver(ibm->acpi->driver);
4011 kfree(ibm->acpi->driver);
4012 ibm->acpi->driver = NULL;
4013 ibm->flags.acpi_driver_registered = 0;
4014 }
4015
4016 if (ibm->flags.init_called && ibm->exit) {
4017 ibm->exit();
4018 ibm->flags.init_called = 0;
4019 }
4020
4021 dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name);
4022}
4023
4024/* Probing */
4025
4026static char *ibm_thinkpad_ec_found = NULL;
4027
4028static char* __init check_dmi_for_ec(void)
4029{
4030 struct dmi_device *dev = NULL;
4031 char ec_fw_string[18];
4032
4033 /*
4034 * ThinkPad T23 or newer, A31 or newer, R50e or newer,
4035 * X32 or newer, all Z series; Some models must have an
4036 * up-to-date BIOS or they will not be detected.
4037 *
4038 * See http://thinkwiki.org/wiki/List_of_DMI_IDs
4039 */
4040 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
4041 if (sscanf(dev->name,
4042 "IBM ThinkPad Embedded Controller -[%17c",
4043 ec_fw_string) == 1) {
4044 ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
4045 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
4046 return kstrdup(ec_fw_string, GFP_KERNEL);
4047 }
4048 }
4049 return NULL;
4050}
4051
4052static int __init probe_for_thinkpad(void)
4053{
4054 int is_thinkpad;
4055
4056 if (acpi_disabled)
4057 return -ENODEV;
4058
4059 /*
4060 * Non-ancient models have better DMI tagging, but very old models
4061 * don't.
4062 */
4063 is_thinkpad = dmi_name_in_vendors("ThinkPad");
4064
4065 /* ec is required because many other handles are relative to it */
4066 IBM_ACPIHANDLE_INIT(ec);
4067 if (!ec_handle) {
4068 if (is_thinkpad)
4069 printk(IBM_ERR
4070 "Not yet supported ThinkPad detected!\n");
4071 return -ENODEV;
4072 }
4073
4074 /*
4075 * Risks a regression on very old machines, but reduces potential
4076 * false positives a damn great deal
4077 */
4078 if (!is_thinkpad)
4079 is_thinkpad = dmi_name_in_vendors("IBM");
4080
4081 if (!is_thinkpad && !force_load)
4082 return -ENODEV;
4083
4084 return 0;
4085}
4086
4087
4088/* Module init, exit, parameters */
4089
4090static struct ibm_init_struct ibms_init[] __initdata = {
4091 {
4092 .init = thinkpad_acpi_driver_init,
4093 .data = &thinkpad_acpi_driver_data,
4094 },
4095 {
4096 .init = hotkey_init,
4097 .data = &hotkey_driver_data,
4098 },
4099 {
4100 .init = bluetooth_init,
4101 .data = &bluetooth_driver_data,
4102 },
4103 {
4104 .init = wan_init,
4105 .data = &wan_driver_data,
4106 },
4107 {
4108 .init = video_init,
4109 .data = &video_driver_data,
4110 },
4111 {
4112 .init = light_init,
4113 .data = &light_driver_data,
4114 },
4115#ifdef CONFIG_THINKPAD_ACPI_DOCK
4116 {
4117 .init = dock_init,
4118 .data = &dock_driver_data[0],
4119 },
4120 {
4121 .init = dock_init2,
4122 .data = &dock_driver_data[1],
4123 },
4124#endif
4125#ifdef CONFIG_THINKPAD_ACPI_BAY
4126 {
4127 .init = bay_init,
4128 .data = &bay_driver_data,
4129 },
4130#endif
4131 {
4132 .init = cmos_init,
4133 .data = &cmos_driver_data,
4134 },
4135 {
4136 .init = led_init,
4137 .data = &led_driver_data,
4138 },
4139 {
4140 .init = beep_init,
4141 .data = &beep_driver_data,
4142 },
4143 {
4144 .init = thermal_init,
4145 .data = &thermal_driver_data,
4146 },
4147 {
4148 .data = &ecdump_driver_data,
4149 },
4150 {
4151 .init = brightness_init,
4152 .data = &brightness_driver_data,
4153 },
4154 {
4155 .data = &volume_driver_data,
4156 },
4157 {
4158 .init = fan_init,
4159 .data = &fan_driver_data,
4160 },
4161};
4162
4163static int __init set_ibm_param(const char *val, struct kernel_param *kp)
4164{
4165 unsigned int i;
4166 struct ibm_struct *ibm;
4167
4168 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
4169 ibm = ibms_init[i].data;
4170 BUG_ON(ibm == NULL);
4171
4172 if (strcmp(ibm->name, kp->name) == 0 && ibm->write) {
4173 if (strlen(val) > sizeof(ibms_init[i].param) - 2)
4174 return -ENOSPC;
4175 strcpy(ibms_init[i].param, val);
4176 strcat(ibms_init[i].param, ",");
4177 return 0;
4178 }
4179 }
4180
4181 return -EINVAL;
4182}
4183
4184static int experimental;
4185module_param(experimental, int, 0);
4186
4187static u32 dbg_level;
4188module_param_named(debug, dbg_level, uint, 0);
4189
4190static int force_load;
4191module_param(force_load, int, 0);
4192
4193static int fan_control_allowed;
4194module_param_named(fan_control, fan_control_allowed, int, 0);
4195
4196#define IBM_PARAM(feature) \
4197 module_param_call(feature, set_ibm_param, NULL, NULL, 0)
4198
4199IBM_PARAM(hotkey);
4200IBM_PARAM(bluetooth);
4201IBM_PARAM(video);
4202IBM_PARAM(light);
4203#ifdef CONFIG_THINKPAD_ACPI_DOCK
4204IBM_PARAM(dock);
4205#endif
4206#ifdef CONFIG_THINKPAD_ACPI_BAY
4207IBM_PARAM(bay);
4208#endif /* CONFIG_THINKPAD_ACPI_BAY */
4209IBM_PARAM(cmos);
4210IBM_PARAM(led);
4211IBM_PARAM(beep);
4212IBM_PARAM(ecdump);
4213IBM_PARAM(brightness);
4214IBM_PARAM(volume);
4215IBM_PARAM(fan);
4216
4217static int __init thinkpad_acpi_module_init(void)
4218{
4219 int ret, i;
4220
4221 /* Driver-level probe */
4222 ret = probe_for_thinkpad();
4223 if (ret)
4224 return ret;
4225
4226 /* Driver initialization */
4227 ibm_thinkpad_ec_found = check_dmi_for_ec();
4228 IBM_ACPIHANDLE_INIT(ecrd);
4229 IBM_ACPIHANDLE_INIT(ecwr);
4230
4231 proc_dir = proc_mkdir(IBM_PROC_DIR, acpi_root_dir);
4232 if (!proc_dir) {
4233 printk(IBM_ERR "unable to create proc dir " IBM_PROC_DIR);
4234 thinkpad_acpi_module_exit();
4235 return -ENODEV;
4236 }
4237 proc_dir->owner = THIS_MODULE;
4238
4239 ret = platform_driver_register(&tpacpi_pdriver);
4240 if (ret) {
4241 printk(IBM_ERR "unable to register platform driver\n");
4242 thinkpad_acpi_module_exit();
4243 return ret;
4244 }
4245 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
4246 if (ret) {
4247 printk(IBM_ERR "unable to create sysfs driver attributes\n");
4248 thinkpad_acpi_module_exit();
4249 return ret;
4250 }
4251
4252
4253 /* Device initialization */
4254 tpacpi_pdev = platform_device_register_simple(IBM_DRVR_NAME, -1,
4255 NULL, 0);
4256 if (IS_ERR(tpacpi_pdev)) {
4257 ret = PTR_ERR(tpacpi_pdev);
4258 tpacpi_pdev = NULL;
4259 printk(IBM_ERR "unable to register platform device\n");
4260 thinkpad_acpi_module_exit();
4261 return ret;
4262 }
4263 tpacpi_hwmon = hwmon_device_register(&tpacpi_pdev->dev);
4264 if (IS_ERR(tpacpi_hwmon)) {
4265 ret = PTR_ERR(tpacpi_hwmon);
4266 tpacpi_hwmon = NULL;
4267 printk(IBM_ERR "unable to register hwmon device\n");
4268 thinkpad_acpi_module_exit();
4269 return ret;
4270 }
4271 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
4272 ret = ibm_init(&ibms_init[i]);
4273 if (ret >= 0 && *ibms_init[i].param)
4274 ret = ibms_init[i].data->write(ibms_init[i].param);
4275 if (ret < 0) {
4276 thinkpad_acpi_module_exit();
4277 return ret;
4278 }
4279 }
4280
4281 return 0;
4282}
4283
4284static void thinkpad_acpi_module_exit(void)
4285{
4286 struct ibm_struct *ibm, *itmp;
4287
4288 list_for_each_entry_safe_reverse(ibm, itmp,
4289 &tpacpi_all_drivers,
4290 all_drivers) {
4291 ibm_exit(ibm);
4292 }
4293
4294 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
4295
4296 if (tpacpi_hwmon)
4297 hwmon_device_unregister(tpacpi_hwmon);
4298
4299 if (tpacpi_pdev)
4300 platform_device_unregister(tpacpi_pdev);
4301
4302 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
4303 platform_driver_unregister(&tpacpi_pdriver);
4304
4305 if (proc_dir)
4306 remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
4307
4308 kfree(ibm_thinkpad_ec_found);
4309}
4310
4311module_init(thinkpad_acpi_module_init);
4312module_exit(thinkpad_acpi_module_exit);
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
new file mode 100644
index 000000000000..440145a02617
--- /dev/null
+++ b/drivers/misc/thinkpad_acpi.h
@@ -0,0 +1,572 @@
1/*
2 * thinkpad_acpi.h - ThinkPad ACPI Extras
3 *
4 *
5 * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
6 * Copyright (C) 2006-2007 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#ifndef __THINKPAD_ACPI_H__
25#define __THINKPAD_ACPI_H__
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/types.h>
31#include <linux/string.h>
32#include <linux/list.h>
33#include <linux/mutex.h>
34
35#include <linux/proc_fs.h>
36#include <linux/sysfs.h>
37#include <linux/backlight.h>
38#include <linux/fb.h>
39#include <linux/platform_device.h>
40#include <linux/hwmon.h>
41#include <linux/hwmon-sysfs.h>
42#include <asm/uaccess.h>
43
44#include <linux/dmi.h>
45#include <linux/jiffies.h>
46#include <linux/workqueue.h>
47
48#include <acpi/acpi_drivers.h>
49#include <acpi/acnamesp.h>
50
51
52/****************************************************************************
53 * Main driver
54 */
55
56#define IBM_NAME "thinkpad"
57#define IBM_DESC "ThinkPad ACPI Extras"
58#define IBM_FILE "thinkpad_acpi"
59#define IBM_URL "http://ibm-acpi.sf.net/"
60#define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net"
61
62#define IBM_PROC_DIR "ibm"
63#define IBM_ACPI_EVENT_PREFIX "ibm"
64#define IBM_DRVR_NAME IBM_FILE
65
66#define IBM_LOG IBM_FILE ": "
67#define IBM_ERR KERN_ERR IBM_LOG
68#define IBM_NOTICE KERN_NOTICE IBM_LOG
69#define IBM_INFO KERN_INFO IBM_LOG
70#define IBM_DEBUG KERN_DEBUG IBM_LOG
71
72#define IBM_MAX_ACPI_ARGS 3
73
74/* ThinkPad CMOS commands */
75#define TP_CMOS_VOLUME_DOWN 0
76#define TP_CMOS_VOLUME_UP 1
77#define TP_CMOS_VOLUME_MUTE 2
78#define TP_CMOS_BRIGHTNESS_UP 4
79#define TP_CMOS_BRIGHTNESS_DOWN 5
80
81#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
82#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
83#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
84
85/* Debugging */
86#define TPACPI_DBG_ALL 0xffff
87#define TPACPI_DBG_ALL 0xffff
88#define TPACPI_DBG_INIT 0x0001
89#define TPACPI_DBG_EXIT 0x0002
90#define dbg_printk(a_dbg_level, format, arg...) \
91 do { if (dbg_level & a_dbg_level) \
92 printk(IBM_DEBUG "%s: " format, __func__ , ## arg); } while (0)
93#ifdef CONFIG_THINKPAD_ACPI_DEBUG
94#define vdbg_printk(a_dbg_level, format, arg...) \
95 dbg_printk(a_dbg_level, format, ## arg)
96static const char *str_supported(int is_supported);
97#else
98#define vdbg_printk(a_dbg_level, format, arg...)
99#endif
100
101/* ACPI HIDs */
102#define IBM_HKEY_HID "IBM0068"
103#define IBM_PCI_HID "PNP0A03"
104
105/* ACPI helpers */
106static int __must_check acpi_evalf(acpi_handle handle,
107 void *res, char *method, char *fmt, ...);
108static int __must_check acpi_ec_read(int i, u8 * p);
109static int __must_check acpi_ec_write(int i, u8 v);
110static int __must_check _sta(acpi_handle handle);
111
112/* ACPI handles */
113static acpi_handle root_handle; /* root namespace */
114static acpi_handle ec_handle; /* EC */
115static acpi_handle ecrd_handle, ecwr_handle; /* 570 EC access */
116static acpi_handle cmos_handle, hkey_handle; /* basic thinkpad handles */
117
118static void drv_acpi_handle_init(char *name,
119 acpi_handle *handle, acpi_handle parent,
120 char **paths, int num_paths, char **path);
121#define IBM_ACPIHANDLE_INIT(object) \
122 drv_acpi_handle_init(#object, &object##_handle, *object##_parent, \
123 object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
124
125/* ThinkPad ACPI helpers */
126static int issue_thinkpad_cmos_command(int cmos_cmd);
127
128/* procfs support */
129static struct proc_dir_entry *proc_dir;
130
131/* procfs helpers */
132static int dispatch_procfs_read(char *page, char **start, off_t off,
133 int count, int *eof, void *data);
134static int dispatch_procfs_write(struct file *file,
135 const char __user * userbuf,
136 unsigned long count, void *data);
137static char *next_cmd(char **cmds);
138
139/* sysfs support */
140struct attribute_set {
141 unsigned int members, max_members;
142 struct attribute_group group;
143};
144
145static struct attribute_set *create_attr_set(unsigned int max_members,
146 const char* name);
147#define destroy_attr_set(_set) \
148 kfree(_set);
149static int add_to_attr_set(struct attribute_set* s, struct attribute *attr);
150static int add_many_to_attr_set(struct attribute_set* s,
151 struct attribute **attr,
152 unsigned int count);
153#define register_attr_set_with_sysfs(_attr_set, _kobj) \
154 sysfs_create_group(_kobj, &_attr_set->group)
155static void delete_attr_set(struct attribute_set* s, struct kobject *kobj);
156
157static int parse_strtoul(const char *buf, unsigned long max,
158 unsigned long *value);
159
160/* Device model */
161static struct platform_device *tpacpi_pdev;
162static struct class_device *tpacpi_hwmon;
163static struct platform_driver tpacpi_pdriver;
164static int tpacpi_create_driver_attributes(struct device_driver *drv);
165static void tpacpi_remove_driver_attributes(struct device_driver *drv);
166
167/* Module */
168static int experimental;
169static u32 dbg_level;
170static int force_load;
171static char *ibm_thinkpad_ec_found;
172
173static char* check_dmi_for_ec(void);
174static int thinkpad_acpi_module_init(void);
175static void thinkpad_acpi_module_exit(void);
176
177
178/****************************************************************************
179 * Subdrivers
180 */
181
182struct ibm_struct;
183
184struct tp_acpi_drv_struct {
185 char *hid;
186 struct acpi_driver *driver;
187
188 void (*notify) (struct ibm_struct *, u32);
189 acpi_handle *handle;
190 u32 type;
191 struct acpi_device *device;
192};
193
194struct ibm_struct {
195 char *name;
196
197 int (*read) (char *);
198 int (*write) (char *);
199 void (*exit) (void);
200
201 struct list_head all_drivers;
202
203 struct tp_acpi_drv_struct *acpi;
204
205 struct {
206 u8 acpi_driver_registered:1;
207 u8 acpi_notify_installed:1;
208 u8 proc_created:1;
209 u8 init_called:1;
210 u8 experimental:1;
211 } flags;
212};
213
214struct ibm_init_struct {
215 char param[32];
216
217 int (*init) (struct ibm_init_struct *);
218 struct ibm_struct *data;
219};
220
221static struct {
222#ifdef CONFIG_THINKPAD_ACPI_BAY
223 u16 bay_status:1;
224 u16 bay_eject:1;
225 u16 bay_status2:1;
226 u16 bay_eject2:1;
227#endif
228 u16 bluetooth:1;
229 u16 hotkey:1;
230 u16 hotkey_mask:1;
231 u16 light:1;
232 u16 light_status:1;
233 u16 wan:1;
234 u16 fan_ctrl_status_undef:1;
235} tp_features;
236
237static struct list_head tpacpi_all_drivers;
238
239static struct ibm_init_struct ibms_init[];
240static int set_ibm_param(const char *val, struct kernel_param *kp);
241static int ibm_init(struct ibm_init_struct *iibm);
242static void ibm_exit(struct ibm_struct *ibm);
243
244
245/*
246 * procfs master subdriver
247 */
248static int thinkpad_acpi_driver_init(struct ibm_init_struct *iibm);
249static int thinkpad_acpi_driver_read(char *p);
250
251
252/*
253 * Bay subdriver
254 */
255
256#ifdef CONFIG_THINKPAD_ACPI_BAY
257static acpi_handle bay_handle, bay_ej_handle;
258static acpi_handle bay2_handle, bay2_ej_handle;
259
260static int bay_init(struct ibm_init_struct *iibm);
261static void bay_notify(struct ibm_struct *ibm, u32 event);
262static int bay_read(char *p);
263static int bay_write(char *buf);
264#endif /* CONFIG_THINKPAD_ACPI_BAY */
265
266
267/*
268 * Beep subdriver
269 */
270
271static acpi_handle beep_handle;
272
273static int beep_read(char *p);
274static int beep_write(char *buf);
275
276
277/*
278 * Bluetooth subdriver
279 */
280
281#define TPACPI_BLUETH_SYSFS_GROUP "bluetooth"
282
283enum {
284 /* ACPI GBDC/SBDC bits */
285 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */
286 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */
287 TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */
288};
289
290static int bluetooth_init(struct ibm_init_struct *iibm);
291static int bluetooth_get_radiosw(void);
292static int bluetooth_set_radiosw(int radio_on);
293static int bluetooth_read(char *p);
294static int bluetooth_write(char *buf);
295
296
297/*
298 * Brightness (backlight) subdriver
299 */
300
301#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
302
303static struct backlight_device *ibm_backlight_device;
304static int brightness_offset = 0x31;
305
306static int brightness_init(struct ibm_init_struct *iibm);
307static void brightness_exit(void);
308static int brightness_get(struct backlight_device *bd);
309static int brightness_set(int value);
310static int brightness_update_status(struct backlight_device *bd);
311static int brightness_read(char *p);
312static int brightness_write(char *buf);
313
314
315/*
316 * CMOS subdriver
317 */
318
319static int cmos_read(char *p);
320static int cmos_write(char *buf);
321
322
323/*
324 * Dock subdriver
325 */
326
327#ifdef CONFIG_THINKPAD_ACPI_DOCK
328static acpi_handle pci_handle;
329static acpi_handle dock_handle;
330
331static void dock_notify(struct ibm_struct *ibm, u32 event);
332static int dock_read(char *p);
333static int dock_write(char *buf);
334#endif /* CONFIG_THINKPAD_ACPI_DOCK */
335
336
337/*
338 * EC dump subdriver
339 */
340
341static int ecdump_read(char *p) ;
342static int ecdump_write(char *buf);
343
344
345/*
346 * Fan subdriver
347 */
348
349enum { /* Fan control constants */
350 fan_status_offset = 0x2f, /* EC register 0x2f */
351 fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM)
352 * 0x84 must be read before 0x85 */
353
354 TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */
355 TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */
356
357 TPACPI_FAN_LAST_LEVEL = 0x100, /* Use cached last-seen fan level */
358};
359
360enum fan_status_access_mode {
361 TPACPI_FAN_NONE = 0, /* No fan status or control */
362 TPACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */
363 TPACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */
364};
365
366enum fan_control_access_mode {
367 TPACPI_FAN_WR_NONE = 0, /* No fan control */
368 TPACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */
369 TPACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */
370 TPACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */
371};
372
373enum fan_control_commands {
374 TPACPI_FAN_CMD_SPEED = 0x0001, /* speed command */
375 TPACPI_FAN_CMD_LEVEL = 0x0002, /* level command */
376 TPACPI_FAN_CMD_ENABLE = 0x0004, /* enable/disable cmd,
377 * and also watchdog cmd */
378};
379
380static int fan_control_allowed;
381
382static enum fan_status_access_mode fan_status_access_mode;
383static enum fan_control_access_mode fan_control_access_mode;
384static enum fan_control_commands fan_control_commands;
385static u8 fan_control_initial_status;
386static u8 fan_control_desired_level;
387static int fan_watchdog_maxinterval;
388
389static struct mutex fan_mutex;
390
391static acpi_handle fans_handle, gfan_handle, sfan_handle;
392
393static int fan_init(struct ibm_init_struct *iibm);
394static void fan_exit(void);
395static int fan_get_status(u8 *status);
396static int fan_get_status_safe(u8 *status);
397static int fan_get_speed(unsigned int *speed);
398static void fan_update_desired_level(u8 status);
399static void fan_watchdog_fire(struct work_struct *ignored);
400static void fan_watchdog_reset(void);
401static int fan_set_level(int level);
402static int fan_set_level_safe(int level);
403static int fan_set_enable(void);
404static int fan_set_disable(void);
405static int fan_set_speed(int speed);
406static int fan_read(char *p);
407static int fan_write(char *buf);
408static int fan_write_cmd_level(const char *cmd, int *rc);
409static int fan_write_cmd_enable(const char *cmd, int *rc);
410static int fan_write_cmd_disable(const char *cmd, int *rc);
411static int fan_write_cmd_speed(const char *cmd, int *rc);
412static int fan_write_cmd_watchdog(const char *cmd, int *rc);
413
414
415/*
416 * Hotkey subdriver
417 */
418
419#define TPACPI_HOTKEY_SYSFS_GROUP "hotkey"
420
421static int hotkey_orig_status;
422static int hotkey_orig_mask;
423
424static struct mutex hotkey_mutex;
425
426static int hotkey_init(struct ibm_init_struct *iibm);
427static void hotkey_exit(void);
428static int hotkey_get(int *status, int *mask);
429static int hotkey_set(int status, int mask);
430static void hotkey_notify(struct ibm_struct *ibm, u32 event);
431static int hotkey_read(char *p);
432static int hotkey_write(char *buf);
433
434
435/*
436 * LED subdriver
437 */
438
439enum led_access_mode {
440 TPACPI_LED_NONE = 0,
441 TPACPI_LED_570, /* 570 */
442 TPACPI_LED_OLD, /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
443 TPACPI_LED_NEW, /* all others */
444};
445
446enum { /* For TPACPI_LED_OLD */
447 TPACPI_LED_EC_HLCL = 0x0c, /* EC reg to get led to power on */
448 TPACPI_LED_EC_HLBL = 0x0d, /* EC reg to blink a lit led */
449 TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */
450};
451
452static enum led_access_mode led_supported;
453static acpi_handle led_handle;
454
455static int led_init(struct ibm_init_struct *iibm);
456static int led_read(char *p);
457static int led_write(char *buf);
458
459/*
460 * Light (thinklight) subdriver
461 */
462
463static acpi_handle lght_handle, ledb_handle;
464
465static int light_init(struct ibm_init_struct *iibm);
466static int light_read(char *p);
467static int light_write(char *buf);
468
469
470/*
471 * Thermal subdriver
472 */
473
474enum thermal_access_mode {
475 TPACPI_THERMAL_NONE = 0, /* No thermal support */
476 TPACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */
477 TPACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */
478 TPACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */
479 TPACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */
480};
481
482enum { /* TPACPI_THERMAL_TPEC_* */
483 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */
484 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */
485 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */
486};
487
488#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
489struct ibm_thermal_sensors_struct {
490 s32 temp[TPACPI_MAX_THERMAL_SENSORS];
491};
492
493static enum thermal_access_mode thermal_read_mode;
494
495static int thermal_init(struct ibm_init_struct *iibm);
496static int thermal_get_sensor(int idx, s32 *value);
497static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s);
498static int thermal_read(char *p);
499
500
501/*
502 * Video subdriver
503 */
504
505enum video_access_mode {
506 TPACPI_VIDEO_NONE = 0,
507 TPACPI_VIDEO_570, /* 570 */
508 TPACPI_VIDEO_770, /* 600e/x, 770e, 770x */
509 TPACPI_VIDEO_NEW, /* all others */
510};
511
512enum { /* video status flags, based on VIDEO_570 */
513 TP_ACPI_VIDEO_S_LCD = 0x01, /* LCD output enabled */
514 TP_ACPI_VIDEO_S_CRT = 0x02, /* CRT output enabled */
515 TP_ACPI_VIDEO_S_DVI = 0x08, /* DVI output enabled */
516};
517
518enum { /* TPACPI_VIDEO_570 constants */
519 TP_ACPI_VIDEO_570_PHSCMD = 0x87, /* unknown magic constant :( */
520 TP_ACPI_VIDEO_570_PHSMASK = 0x03, /* PHS bits that map to
521 * video_status_flags */
522 TP_ACPI_VIDEO_570_PHS2CMD = 0x8b, /* unknown magic constant :( */
523 TP_ACPI_VIDEO_570_PHS2SET = 0x80, /* unknown magic constant :( */
524};
525
526static enum video_access_mode video_supported;
527static int video_orig_autosw;
528static acpi_handle vid_handle, vid2_handle;
529
530static int video_init(struct ibm_init_struct *iibm);
531static void video_exit(void);
532static int video_outputsw_get(void);
533static int video_outputsw_set(int status);
534static int video_autosw_get(void);
535static int video_autosw_set(int enable);
536static int video_outputsw_cycle(void);
537static int video_expand_toggle(void);
538static int video_read(char *p);
539static int video_write(char *buf);
540
541
542/*
543 * Volume subdriver
544 */
545
546static int volume_offset = 0x30;
547
548static int volume_read(char *p);
549static int volume_write(char *buf);
550
551
552/*
553 * Wan subdriver
554 */
555
556#define TPACPI_WAN_SYSFS_GROUP "wwan"
557
558enum {
559 /* ACPI GWAN/SWAN bits */
560 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */
561 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */
562 TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */
563};
564
565static int wan_init(struct ibm_init_struct *iibm);
566static int wan_get_radiosw(void);
567static int wan_set_radiosw(int radio_on);
568static int wan_read(char *p);
569static int wan_write(char *buf);
570
571
572#endif /* __THINKPAD_ACPI_H */
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index a064f36a0805..b5ac810404c0 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -317,6 +317,10 @@ static int __init acpi_pci_init(void)
317{ 317{
318 int ret; 318 int ret;
319 319
320 if (acpi_gbl_FADT.boot_flags & BAF_MSI_NOT_SUPPORTED) {
321 printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
322 pci_no_msi();
323 }
320 ret = register_acpi_bus_type(&acpi_pci_bus); 324 ret = register_acpi_bus_type(&acpi_pci_bus);
321 if (ret) 325 if (ret)
322 return 0; 326 return 0;
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index 09469e7db6a5..955adfb8d64c 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -276,6 +276,7 @@ enum acpi_prefered_pm_profiles {
276 276
277#define BAF_LEGACY_DEVICES 0x0001 277#define BAF_LEGACY_DEVICES 0x0001
278#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 278#define BAF_8042_KEYBOARD_CONTROLLER 0x0002
279#define BAF_MSI_NOT_SUPPORTED 0x0008
279 280
280#define FADT2_REVISION_ID 3 281#define FADT2_REVISION_ID 3
281#define FADT2_MINUS_REVISION_ID 2 282#define FADT2_MINUS_REVISION_ID 2
diff --git a/include/linux/sony-laptop.h b/include/linux/sony-laptop.h
new file mode 100644
index 000000000000..e2e036d94e4a
--- /dev/null
+++ b/include/linux/sony-laptop.h
@@ -0,0 +1,34 @@
1#ifndef _SONYLAPTOP_H_
2#define _SONYLAPTOP_H_
3
4#include <linux/types.h>
5
6#ifdef __KERNEL__
7
8/* used only for communication between v4l and sony-laptop */
9
10#define SONY_PIC_COMMAND_GETCAMERA 1 /* obsolete */
11#define SONY_PIC_COMMAND_SETCAMERA 2
12#define SONY_PIC_COMMAND_GETCAMERABRIGHTNESS 3 /* obsolete */
13#define SONY_PIC_COMMAND_SETCAMERABRIGHTNESS 4
14#define SONY_PIC_COMMAND_GETCAMERACONTRAST 5 /* obsolete */
15#define SONY_PIC_COMMAND_SETCAMERACONTRAST 6
16#define SONY_PIC_COMMAND_GETCAMERAHUE 7 /* obsolete */
17#define SONY_PIC_COMMAND_SETCAMERAHUE 8
18#define SONY_PIC_COMMAND_GETCAMERACOLOR 9 /* obsolete */
19#define SONY_PIC_COMMAND_SETCAMERACOLOR 10
20#define SONY_PIC_COMMAND_GETCAMERASHARPNESS 11 /* obsolete */
21#define SONY_PIC_COMMAND_SETCAMERASHARPNESS 12
22#define SONY_PIC_COMMAND_GETCAMERAPICTURE 13 /* obsolete */
23#define SONY_PIC_COMMAND_SETCAMERAPICTURE 14
24#define SONY_PIC_COMMAND_GETCAMERAAGC 15 /* obsolete */
25#define SONY_PIC_COMMAND_SETCAMERAAGC 16
26#define SONY_PIC_COMMAND_GETCAMERADIRECTION 17 /* obsolete */
27#define SONY_PIC_COMMAND_GETCAMERAROMVERSION 18 /* obsolete */
28#define SONY_PIC_COMMAND_GETCAMERAREVISION 19 /* obsolete */
29
30int sony_pic_camera_command(int command, u8 value);
31
32#endif /* __KERNEL__ */
33
34#endif /* _SONYLAPTOP_H_ */