diff options
-rw-r--r-- | drivers/staging/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/pcc-acpi/Kconfig | 11 | ||||
-rw-r--r-- | drivers/staging/pcc-acpi/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/pcc-acpi/TODO | 7 | ||||
-rw-r--r-- | drivers/staging/pcc-acpi/pcc-acpi.c | 1111 |
6 files changed, 0 insertions, 1133 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index c4eff44c9f27..e1654f59eb70 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -43,8 +43,6 @@ source "drivers/staging/echo/Kconfig" | |||
43 | 43 | ||
44 | source "drivers/staging/at76_usb/Kconfig" | 44 | source "drivers/staging/at76_usb/Kconfig" |
45 | 45 | ||
46 | source "drivers/staging/pcc-acpi/Kconfig" | ||
47 | |||
48 | source "drivers/staging/poch/Kconfig" | 46 | source "drivers/staging/poch/Kconfig" |
49 | 47 | ||
50 | endif # STAGING | 48 | endif # STAGING |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 7cb8701d96d4..71c4d53760b8 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -13,5 +13,4 @@ obj-$(CONFIG_W35UND) += winbond/ | |||
13 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ | 13 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ |
14 | obj-$(CONFIG_ECHO) += echo/ | 14 | obj-$(CONFIG_ECHO) += echo/ |
15 | obj-$(CONFIG_USB_ATMEL) += at76_usb/ | 15 | obj-$(CONFIG_USB_ATMEL) += at76_usb/ |
16 | obj-$(CONFIG_PCC_ACPI) += pcc-acpi/ | ||
17 | obj-$(CONFIG_POCH) += poch/ | 16 | obj-$(CONFIG_POCH) += poch/ |
diff --git a/drivers/staging/pcc-acpi/Kconfig b/drivers/staging/pcc-acpi/Kconfig deleted file mode 100644 index 6720d4086baf..000000000000 --- a/drivers/staging/pcc-acpi/Kconfig +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | config PCC_ACPI | ||
2 | tristate "Panasonic ACPI Hotkey support" | ||
3 | depends on ACPI | ||
4 | default n | ||
5 | ---help--- | ||
6 | This driver provides support for Panasonic hotkeys through the | ||
7 | ACPI interface. This works for the Panasonic R1 (N variant), | ||
8 | R2, R3, T2, W2, and Y2 laptops. | ||
9 | |||
10 | To compile this driver as a module, choose M here. The module | ||
11 | will be called pcc-acpi. | ||
diff --git a/drivers/staging/pcc-acpi/Makefile b/drivers/staging/pcc-acpi/Makefile deleted file mode 100644 index f93b29edf61e..000000000000 --- a/drivers/staging/pcc-acpi/Makefile +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | obj-$(CONFIG_PCC_ACPI) += pcc-acpi.o | ||
diff --git a/drivers/staging/pcc-acpi/TODO b/drivers/staging/pcc-acpi/TODO deleted file mode 100644 index fab240982286..000000000000 --- a/drivers/staging/pcc-acpi/TODO +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | TODO: | ||
2 | - Lindent fixes | ||
3 | - checkpatch.pl fixes | ||
4 | - verify that the acpi interface is correct | ||
5 | - remove /proc dependancy if needed (not sure yet.) | ||
6 | |||
7 | Please send any patches for this driver to Greg Kroah-Hartman <greg@kroah.com> | ||
diff --git a/drivers/staging/pcc-acpi/pcc-acpi.c b/drivers/staging/pcc-acpi/pcc-acpi.c deleted file mode 100644 index 3b34a3e4885a..000000000000 --- a/drivers/staging/pcc-acpi/pcc-acpi.c +++ /dev/null | |||
@@ -1,1111 +0,0 @@ | |||
1 | /* | ||
2 | * Panasonic HotKey and lcd brightness control Extra driver | ||
3 | * (C) 2004 Hiroshi Miura <miura@da-cha.org> | ||
4 | * (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/ | ||
5 | * (C) YOKOTA Hiroshi <yokota (at) netlab. is. tsukuba. ac. jp> | ||
6 | * (C) 2004 David Bronaugh <dbronaugh> | ||
7 | * | ||
8 | * derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * publicshed by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | *--------------------------------------------------------------------------- | ||
24 | * | ||
25 | * ChangeLog: | ||
26 | * | ||
27 | * Nov.04, 2006 Hiroshi Miura <miura@da-cha.org> | ||
28 | * -v0.9 remove warning about section reference. | ||
29 | * remove acpi_os_free | ||
30 | * add /proc/acpi/pcc/brightness interface to | ||
31 | * allow HAL to access. | ||
32 | * merge dbronaugh's enhancement | ||
33 | * Aug.17, 2004 David Bronaugh (dbronaugh) | ||
34 | * - Added screen brightness setting interface | ||
35 | * Thanks to the FreeBSD crew | ||
36 | * (acpi_panasonic.c authors) | ||
37 | * for the ideas I needed to accomplish it | ||
38 | * | ||
39 | * May.29, 2006 Hiroshi Miura <miura@da-cha.org> | ||
40 | * -v0.8.4 follow to change keyinput structure | ||
41 | * thanks Fabian Yamaguchi <fabs@cs.tu-berlin.de>, | ||
42 | * Jacob Bower <jacob.bower@ic.ac.uk> and | ||
43 | * Hiroshi Yokota for providing solutions. | ||
44 | * | ||
45 | * Oct.02, 2004 Hiroshi Miura <miura@da-cha.org> | ||
46 | * -v0.8.2 merge code of YOKOTA Hiroshi | ||
47 | * <yokota@netlab.is.tsukuba.ac.jp>. | ||
48 | * Add sticky key mode interface. | ||
49 | * Refactoring acpi_pcc_generete_keyinput(). | ||
50 | * | ||
51 | * Sep.15, 2004 Hiroshi Miura <miura@da-cha.org> | ||
52 | * -v0.8 Generate key input event on input subsystem. | ||
53 | * This is based on yet another driver | ||
54 | * written by Ryuta Nakanishi. | ||
55 | * | ||
56 | * Sep.10, 2004 Hiroshi Miura <miura@da-cha.org> | ||
57 | * -v0.7 Change proc interface functions using seq_file | ||
58 | * facility as same as other ACPI drivers. | ||
59 | * | ||
60 | * Aug.28, 2004 Hiroshi Miura <miura@da-cha.org> | ||
61 | * -v0.6.4 Fix a silly error with status checking | ||
62 | * | ||
63 | * Aug.25, 2004 Hiroshi Miura <miura@da-cha.org> | ||
64 | * -v0.6.3 replace read_acpi_int by standard | ||
65 | * function acpi_evaluate_integer | ||
66 | * some clean up and make smart copyright notice. | ||
67 | * fix return value of pcc_acpi_get_key() | ||
68 | * fix checking return value of acpi_bus_register_driver() | ||
69 | * | ||
70 | * Aug.22, 2004 David Bronaugh <dbronaugh@linuxboxen.org> | ||
71 | * -v0.6.2 Add check on ACPI data (num_sifr) | ||
72 | * Coding style cleanups, better error messages/handling | ||
73 | * Fixed an off-by-one error in memory allocation | ||
74 | * | ||
75 | * Aug.21, 2004 David Bronaugh <dbronaugh@linuxboxen.org> | ||
76 | * -v0.6.1 Fix a silly error with status checking | ||
77 | * | ||
78 | * Aug.20, 2004 David Bronaugh <dbronaugh@linuxboxen.org> | ||
79 | * - v0.6 Correct brightness controls to reflect reality | ||
80 | * based on information gleaned by Hiroshi Miura | ||
81 | * and discussions with Hiroshi Miura | ||
82 | * | ||
83 | * Aug.10, 2004 Hiroshi Miura <miura@da-cha.org> | ||
84 | * - v0.5 support LCD brightness control | ||
85 | * based on the disclosed information by MEI. | ||
86 | * | ||
87 | * Jul.25, 2004 Hiroshi Miura <miura@da-cha.org> | ||
88 | * - v0.4 first post version | ||
89 | * add function to retrive SIFR | ||
90 | * | ||
91 | * Jul.24, 2004 Hiroshi Miura <miura@da-cha.org> | ||
92 | * - v0.3 get proper status of hotkey | ||
93 | * | ||
94 | * Jul.22, 2004 Hiroshi Miura <miura@da-cha.org> | ||
95 | * - v0.2 add HotKey handler | ||
96 | * | ||
97 | * Jul.17, 2004 Hiroshi Miura <miura@da-cha.org> | ||
98 | * - v0.1 start from toshiba_acpi driver written by John Belmonte | ||
99 | * | ||
100 | */ | ||
101 | |||
102 | #define ACPI_PCC_VERSION "0.9+hy" | ||
103 | |||
104 | #include <linux/kernel.h> | ||
105 | #include <linux/module.h> | ||
106 | #include <linux/types.h> | ||
107 | #include <linux/ctype.h> | ||
108 | #include <linux/init.h> | ||
109 | #include <linux/input.h> | ||
110 | #include <linux/proc_fs.h> | ||
111 | #include <linux/seq_file.h> | ||
112 | #include <linux/slab.h> | ||
113 | #include <linux/uaccess.h> | ||
114 | #include <acpi/acpi_bus.h> | ||
115 | #include <acpi/acpi_drivers.h> | ||
116 | |||
117 | |||
118 | /************************************************************************* | ||
119 | * "seq" file template definition. | ||
120 | */ | ||
121 | /* "seq" initializer */ | ||
122 | #define SEQ_OPEN_FS(_open_func_name_, _show_func_name_) \ | ||
123 | static int _open_func_name_(struct inode *inode, struct file *file) \ | ||
124 | { \ | ||
125 | return single_open(file, _show_func_name_, PDE(inode)->data); \ | ||
126 | } | ||
127 | |||
128 | /*------------------------------------------------------------------------- | ||
129 | * "seq" fops template for read-only files. | ||
130 | */ | ||
131 | #define SEQ_FILEOPS_R(_open_func_name_) \ | ||
132 | { \ | ||
133 | .open = _open_func_name_, \ | ||
134 | .read = seq_read, \ | ||
135 | .llseek = seq_lseek, \ | ||
136 | .release = single_release, \ | ||
137 | } | ||
138 | |||
139 | /*------------------------------------------------------------------------ | ||
140 | * "seq" fops template for read-write files. | ||
141 | */ | ||
142 | #define SEQ_FILEOPS_RW(_open_func_name_, _write_func_name_) \ | ||
143 | { \ | ||
144 | .open = _open_func_name_ , \ | ||
145 | .read = seq_read, \ | ||
146 | .write = _write_func_name_, \ | ||
147 | .llseek = seq_lseek, \ | ||
148 | .release = single_release, \ | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * "seq" file template definition ended. | ||
153 | *************************************************************************** | ||
154 | */ | ||
155 | #ifndef ACPI_HOTKEY_COMPONENT | ||
156 | #define ACPI_HOTKEY_COMPONENT 0x10000000 | ||
157 | #endif | ||
158 | |||
159 | #define _COMPONENT ACPI_HOTKEY_COMPONENT | ||
160 | ACPI_MODULE_NAME("pcc_acpi"); | ||
161 | |||
162 | MODULE_AUTHOR("Hiroshi Miura, Hiroshi Yokota"); | ||
163 | MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops"); | ||
164 | MODULE_LICENSE("GPL"); | ||
165 | |||
166 | #define LOGPREFIX "pcc_acpi: " | ||
167 | |||
168 | /**************************************************** | ||
169 | * Define ACPI PATHs | ||
170 | ****************************************************/ | ||
171 | /* Lets note hotkeys */ | ||
172 | #define METHOD_HKEY_QUERY "HINF" | ||
173 | #define METHOD_HKEY_SQTY "SQTY" | ||
174 | #define METHOD_HKEY_SINF "SINF" | ||
175 | #define METHOD_HKEY_SSET "SSET" | ||
176 | #define HKEY_NOTIFY 0x80 | ||
177 | |||
178 | /* for brightness control */ | ||
179 | #define LCD_MAX_BRIGHTNESS 255 | ||
180 | /* This may be magical -- beware */ | ||
181 | #define LCD_BRIGHTNESS_INCREMENT 17 | ||
182 | /* Registers of SINF */ | ||
183 | #define SINF_LCD_BRIGHTNESS 4 | ||
184 | |||
185 | /******************************************************************* | ||
186 | * | ||
187 | * definitions for /proc/ interface | ||
188 | * | ||
189 | *******************************************************************/ | ||
190 | #define ACPI_PCC_DRIVER_NAME "pcc_acpi" | ||
191 | #define ACPI_PCC_DEVICE_NAME "PCCExtra" | ||
192 | #define ACPI_PCC_CLASS "pcc" | ||
193 | #define PROC_PCC ACPI_PCC_CLASS | ||
194 | |||
195 | #define ACPI_PCC_INPUT_PHYS "panasonic/hkey0" | ||
196 | |||
197 | /* This is transitional definition */ | ||
198 | #ifndef KEY_BATT | ||
199 | # define KEY_BATT 227 | ||
200 | #endif | ||
201 | |||
202 | #define PROC_STR_MAX_LEN 8 | ||
203 | |||
204 | #define BUS_PCC_HOTKEY BUS_I8042 /*0x1a*/ /* FIXME: BUS_I8042? */ | ||
205 | |||
206 | /* Fn+F4/F5 confricts with Shift+F1/F2 */ | ||
207 | /* This hack avoids key number confrict */ | ||
208 | #define PCC_KEYINPUT_MODE (0) | ||
209 | |||
210 | /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent | ||
211 | ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00 | ||
212 | */ | ||
213 | enum SINF_BITS { SINF_NUM_BATTERIES = 0, | ||
214 | SINF_LCD_TYPE, | ||
215 | SINF_AC_MAX_BRIGHT, | ||
216 | SINF_AC_MIN_BRIGHT, | ||
217 | SINF_AC_CUR_BRIGHT, | ||
218 | /* 4 = R1 only handle SINF_AC_CUR_BRIGHT | ||
219 | * as SINF_CUR_BRIGHT and don't know AC state */ | ||
220 | SINF_DC_MAX_BRIGHT, | ||
221 | SINF_DC_MIN_BRIGHT, | ||
222 | SINF_DC_CUR_BRIGHT, | ||
223 | SINF_MUTE, | ||
224 | SINF_RESERVED, | ||
225 | SINF_ENV_STATE, /* 10 */ | ||
226 | SINF_STICKY_KEY = 0x80, | ||
227 | }; | ||
228 | |||
229 | static struct acpi_device_id pcc_device_ids[] = { | ||
230 | {"MAT0012", 0}, | ||
231 | {"MAT0013", 0}, | ||
232 | {"MAT0018", 0}, | ||
233 | {"MAT0019", 0}, | ||
234 | {"", 0}, | ||
235 | }; | ||
236 | MODULE_DEVICE_TABLE(acpi, pcc_device_ids); | ||
237 | |||
238 | |||
239 | static int __devinit acpi_pcc_hotkey_add(struct acpi_device *device); | ||
240 | static int __devexit acpi_pcc_hotkey_remove(struct acpi_device *device, | ||
241 | int type); | ||
242 | static int acpi_pcc_hotkey_resume(struct acpi_device *device); | ||
243 | |||
244 | |||
245 | static struct acpi_driver acpi_pcc_driver = { | ||
246 | .name = ACPI_PCC_DRIVER_NAME, | ||
247 | .class = ACPI_PCC_CLASS, | ||
248 | .ids = pcc_device_ids, | ||
249 | .ops = { | ||
250 | .add = acpi_pcc_hotkey_add, | ||
251 | .remove = __devexit_p(acpi_pcc_hotkey_remove), | ||
252 | #ifdef CONFIG_PM | ||
253 | /*.suspend = acpi_pcc_hotkey_suspend,*/ | ||
254 | .resume = acpi_pcc_hotkey_resume, | ||
255 | #endif | ||
256 | }, | ||
257 | }; | ||
258 | |||
259 | struct acpi_hotkey { | ||
260 | acpi_handle handle; | ||
261 | struct acpi_device *device; | ||
262 | struct proc_dir_entry *proc_dir_entry; | ||
263 | unsigned long num_sifr; | ||
264 | unsigned long status; | ||
265 | struct input_dev *input_dev; | ||
266 | int sticky_mode; | ||
267 | }; | ||
268 | |||
269 | struct pcc_keyinput { | ||
270 | struct acpi_hotkey *hotkey; | ||
271 | int key_mode; | ||
272 | }; | ||
273 | |||
274 | /* ************************************************************************* | ||
275 | Hotkey driver core | ||
276 | ************************************************************************* */ | ||
277 | /* ------------------------------------------------------------------------- | ||
278 | method access functions | ||
279 | ------------------------------------------------------------------------- */ | ||
280 | static int acpi_pcc_write_sset(struct acpi_hotkey *hotkey, int func, int val) | ||
281 | { | ||
282 | union acpi_object in_objs[] = { | ||
283 | { .integer.type = ACPI_TYPE_INTEGER, | ||
284 | .integer.value = func, }, | ||
285 | { .integer.type = ACPI_TYPE_INTEGER, | ||
286 | .integer.value = val, }, | ||
287 | }; | ||
288 | struct acpi_object_list params = { | ||
289 | .count = ARRAY_SIZE(in_objs), | ||
290 | .pointer = in_objs, | ||
291 | }; | ||
292 | acpi_status status; | ||
293 | |||
294 | ACPI_FUNCTION_TRACE("acpi_pcc_write_sset"); | ||
295 | |||
296 | status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SSET, | ||
297 | ¶ms, NULL); | ||
298 | |||
299 | return_VALUE(status == AE_OK ? AE_OK : AE_ERROR); | ||
300 | } | ||
301 | |||
302 | static inline int acpi_pcc_get_sqty(struct acpi_device *device) | ||
303 | { | ||
304 | unsigned long s; | ||
305 | acpi_status status; | ||
306 | |||
307 | ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty"); | ||
308 | |||
309 | status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY, | ||
310 | NULL, &s); | ||
311 | if (ACPI_SUCCESS(status)) { | ||
312 | return_VALUE(s); | ||
313 | } else { | ||
314 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
315 | "evaluation error HKEY.SQTY\n")); | ||
316 | return_VALUE(-EINVAL); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | static int acpi_pcc_retrieve_biosdata(struct acpi_hotkey *hotkey, u32 *sinf) | ||
321 | { | ||
322 | acpi_status status; | ||
323 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
324 | union acpi_object *hkey = NULL; | ||
325 | int i; | ||
326 | |||
327 | ACPI_FUNCTION_TRACE("acpi_pcc_retrieve_biosdata"); | ||
328 | |||
329 | status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SINF, 0, | ||
330 | &buffer); | ||
331 | if (ACPI_FAILURE(status)) { | ||
332 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
333 | "evaluation error HKEY.SINF\n")); | ||
334 | status = AE_ERROR; | ||
335 | return_VALUE(status); | ||
336 | } | ||
337 | |||
338 | hkey = buffer.pointer; | ||
339 | if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { | ||
340 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); | ||
341 | goto free_buffer; | ||
342 | } | ||
343 | |||
344 | if (hotkey->num_sifr < hkey->package.count) { | ||
345 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
346 | "SQTY reports bad SINF length\n")); | ||
347 | status = AE_ERROR; | ||
348 | goto free_buffer; | ||
349 | } | ||
350 | |||
351 | for (i = 0; i < hkey->package.count; i++) { | ||
352 | union acpi_object *element = &(hkey->package.elements[i]); | ||
353 | if (likely(element->type == ACPI_TYPE_INTEGER)) { | ||
354 | sinf[i] = element->integer.value; | ||
355 | } else { | ||
356 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
357 | "Invalid HKEY.SINF data\n")); | ||
358 | status = AE_ERROR; | ||
359 | break; | ||
360 | } | ||
361 | } | ||
362 | sinf[hkey->package.count] = -1; | ||
363 | |||
364 | free_buffer: | ||
365 | kfree(buffer.pointer); | ||
366 | return_VALUE(status == AE_OK ? AE_OK : AE_ERROR); | ||
367 | } | ||
368 | |||
369 | static int acpi_pcc_read_sinf_field(struct seq_file *seq, int field) | ||
370 | { | ||
371 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *) seq->private; | ||
372 | u32 sinf[hotkey->num_sifr + 1]; | ||
373 | |||
374 | ACPI_FUNCTION_TRACE("acpi_pcc_read_sinf_field"); | ||
375 | |||
376 | if (ACPI_SUCCESS(acpi_pcc_retrieve_biosdata(hotkey, sinf))) | ||
377 | seq_printf(seq, "%u\n", sinf[field]); | ||
378 | else | ||
379 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
380 | "Couldn't retrieve BIOS data\n")); | ||
381 | |||
382 | return_VALUE(AE_OK); | ||
383 | } | ||
384 | |||
385 | /* ------------------------------------------------------------------------- | ||
386 | user interface functions | ||
387 | ------------------------------------------------------------------------- */ | ||
388 | /* read methods */ | ||
389 | /* Sinf read methods */ | ||
390 | #define PCC_SINF_READ_F(_name_, FUNC) \ | ||
391 | static int _name_(struct seq_file *seq, void *offset) \ | ||
392 | { \ | ||
393 | return_VALUE(ACPI_SUCCESS(acpi_pcc_read_sinf_field(seq, \ | ||
394 | (FUNC))) \ | ||
395 | ? 0 : -EINVAL); \ | ||
396 | } | ||
397 | |||
398 | PCC_SINF_READ_F(acpi_pcc_numbatteries_show, SINF_NUM_BATTERIES); | ||
399 | PCC_SINF_READ_F(acpi_pcc_lcdtype_show, SINF_LCD_TYPE); | ||
400 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_max_show, SINF_AC_MAX_BRIGHT); | ||
401 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_min_show, SINF_AC_MIN_BRIGHT); | ||
402 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_show, SINF_AC_CUR_BRIGHT); | ||
403 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_max_show, SINF_DC_MAX_BRIGHT); | ||
404 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_min_show, SINF_DC_MIN_BRIGHT); | ||
405 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_show, SINF_DC_CUR_BRIGHT); | ||
406 | PCC_SINF_READ_F(acpi_pcc_brightness_show, SINF_AC_CUR_BRIGHT); | ||
407 | PCC_SINF_READ_F(acpi_pcc_mute_show, SINF_MUTE); | ||
408 | |||
409 | static int acpi_pcc_sticky_key_show(struct seq_file *seq, void *offset) | ||
410 | { | ||
411 | struct acpi_hotkey *hotkey = seq->private; | ||
412 | |||
413 | ACPI_FUNCTION_TRACE("acpi_pcc_sticky_key_show"); | ||
414 | |||
415 | if (!hotkey || !hotkey->device) | ||
416 | return_VALUE(-EINVAL); | ||
417 | |||
418 | seq_printf(seq, "%d\n", hotkey->sticky_mode); | ||
419 | |||
420 | return_VALUE(0); | ||
421 | } | ||
422 | |||
423 | static int acpi_pcc_keyinput_show(struct seq_file *seq, void *offset) | ||
424 | { | ||
425 | struct acpi_hotkey *hotkey = seq->private; | ||
426 | struct input_dev *hotk_input_dev = hotkey->input_dev; | ||
427 | struct pcc_keyinput *keyinput = input_get_drvdata(hotk_input_dev); | ||
428 | |||
429 | ACPI_FUNCTION_TRACE("acpi_pcc_keyinput_show"); | ||
430 | |||
431 | seq_printf(seq, "%d\n", keyinput->key_mode); | ||
432 | |||
433 | return_VALUE(0); | ||
434 | } | ||
435 | |||
436 | static int acpi_pcc_version_show(struct seq_file *seq, void *offset) | ||
437 | { | ||
438 | struct acpi_hotkey *hotkey = seq->private; | ||
439 | |||
440 | ACPI_FUNCTION_TRACE("acpi_pcc_version_show"); | ||
441 | |||
442 | if (!hotkey || !hotkey->device) | ||
443 | return_VALUE(-EINVAL); | ||
444 | |||
445 | seq_printf(seq, "%s version %s\n", ACPI_PCC_DRIVER_NAME, | ||
446 | ACPI_PCC_VERSION); | ||
447 | seq_printf(seq, "%li functions\n", hotkey->num_sifr); | ||
448 | |||
449 | return_VALUE(0); | ||
450 | } | ||
451 | |||
452 | /* write methods */ | ||
453 | static ssize_t acpi_pcc_write_single_flag(struct file *file, | ||
454 | const char __user *buffer, | ||
455 | size_t count, | ||
456 | int sinf_func) | ||
457 | { | ||
458 | struct seq_file *seq = file->private_data; | ||
459 | struct acpi_hotkey *hotkey = seq->private; | ||
460 | char write_string[PROC_STR_MAX_LEN]; | ||
461 | u32 val; | ||
462 | |||
463 | ACPI_FUNCTION_TRACE("acpi_pcc_write_single_flag"); | ||
464 | |||
465 | if (!hotkey || (count > sizeof(write_string) - 1)) | ||
466 | return_VALUE(-EINVAL); | ||
467 | |||
468 | if (copy_from_user(write_string, buffer, count)) | ||
469 | return_VALUE(-EFAULT); | ||
470 | |||
471 | write_string[count] = '\0'; | ||
472 | |||
473 | if ((sscanf(write_string, "%3i", &val) == 1) && | ||
474 | (val == 0 || val == 1)) | ||
475 | acpi_pcc_write_sset(hotkey, sinf_func, val); | ||
476 | |||
477 | return_VALUE(count); | ||
478 | } | ||
479 | |||
480 | static unsigned long acpi_pcc_write_brightness(struct file *file, | ||
481 | const char __user *buffer, | ||
482 | size_t count, | ||
483 | int min_index, int max_index, | ||
484 | int cur_index) | ||
485 | { | ||
486 | struct seq_file *seq = (struct seq_file *)file->private_data; | ||
487 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *)seq->private; | ||
488 | char write_string[PROC_STR_MAX_LEN]; | ||
489 | u32 bright; | ||
490 | u32 sinf[hotkey->num_sifr + 1]; | ||
491 | |||
492 | ACPI_FUNCTION_TRACE("acpi_pcc_write_brightness"); | ||
493 | |||
494 | if (!hotkey || (count > sizeof(write_string) - 1)) | ||
495 | return_VALUE(-EINVAL); | ||
496 | |||
497 | if (copy_from_user(write_string, buffer, count)) | ||
498 | return_VALUE(-EFAULT); | ||
499 | |||
500 | write_string[count] = '\0'; | ||
501 | |||
502 | if (ACPI_FAILURE(acpi_pcc_retrieve_biosdata(hotkey, sinf))) { | ||
503 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
504 | "Couldn't retrieve BIOS data\n")); | ||
505 | goto end; | ||
506 | } | ||
507 | |||
508 | if ((sscanf(write_string, "%4i", &bright) == 1) && | ||
509 | (bright >= sinf[min_index]) && | ||
510 | (bright <= sinf[max_index])) | ||
511 | acpi_pcc_write_sset(hotkey, cur_index, bright); | ||
512 | |||
513 | end: | ||
514 | return_VALUE(count); | ||
515 | } | ||
516 | |||
517 | static ssize_t acpi_pcc_write_ac_brightness(struct file *file, | ||
518 | const char __user *buffer, | ||
519 | size_t count, loff_t *ppos) | ||
520 | { | ||
521 | return_VALUE(acpi_pcc_write_brightness(file, buffer, count, | ||
522 | SINF_AC_MIN_BRIGHT, | ||
523 | SINF_AC_MAX_BRIGHT, | ||
524 | SINF_AC_CUR_BRIGHT)); | ||
525 | } | ||
526 | |||
527 | static ssize_t acpi_pcc_write_dc_brightness(struct file *file, | ||
528 | const char __user *buffer, | ||
529 | size_t count, loff_t *ppos) | ||
530 | { | ||
531 | return_VALUE(acpi_pcc_write_brightness(file, buffer, count, | ||
532 | SINF_DC_MIN_BRIGHT, | ||
533 | SINF_DC_MAX_BRIGHT, | ||
534 | SINF_DC_CUR_BRIGHT)); | ||
535 | } | ||
536 | |||
537 | static ssize_t acpi_pcc_write_no_brightness(struct file *file, | ||
538 | const char __user *buffer, | ||
539 | size_t count, loff_t *ppos) | ||
540 | { | ||
541 | return acpi_pcc_write_brightness(file, buffer, count, | ||
542 | SINF_AC_MIN_BRIGHT, | ||
543 | SINF_AC_MAX_BRIGHT, | ||
544 | SINF_AC_CUR_BRIGHT); | ||
545 | } | ||
546 | |||
547 | static ssize_t acpi_pcc_write_mute(struct file *file, | ||
548 | const char __user *buffer, | ||
549 | size_t count, loff_t *ppos) | ||
550 | { | ||
551 | return_VALUE(acpi_pcc_write_single_flag(file, buffer, count, | ||
552 | SINF_MUTE)); | ||
553 | } | ||
554 | |||
555 | static ssize_t acpi_pcc_write_sticky_key(struct file *file, | ||
556 | const char __user *buffer, | ||
557 | size_t count, loff_t *ppos) | ||
558 | { | ||
559 | struct seq_file *seq = (struct seq_file *)file->private_data; | ||
560 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *)seq->private; | ||
561 | char write_string[PROC_STR_MAX_LEN]; | ||
562 | int mode; | ||
563 | |||
564 | ACPI_FUNCTION_TRACE("acpi_pcc_write_sticky_key"); | ||
565 | |||
566 | if (!hotkey || (count > sizeof(write_string) - 1)) | ||
567 | return_VALUE(-EINVAL); | ||
568 | |||
569 | if (copy_from_user(write_string, buffer, count)) | ||
570 | return_VALUE(-EFAULT); | ||
571 | |||
572 | write_string[count] = '\0'; | ||
573 | |||
574 | if ((sscanf(write_string, "%3i", &mode) == 1) && | ||
575 | (mode == 0 || mode == 1)) { | ||
576 | acpi_pcc_write_sset(hotkey, SINF_STICKY_KEY, mode); | ||
577 | hotkey->sticky_mode = mode; | ||
578 | } | ||
579 | |||
580 | return_VALUE(count); | ||
581 | } | ||
582 | |||
583 | static ssize_t acpi_pcc_write_keyinput(struct file *file, | ||
584 | const char __user *buffer, | ||
585 | size_t count, loff_t *ppos) | ||
586 | { | ||
587 | struct seq_file *seq = (struct seq_file *)file->private_data; | ||
588 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *)seq->private; | ||
589 | struct pcc_keyinput *keyinput; | ||
590 | char write_string[PROC_STR_MAX_LEN]; | ||
591 | int key_mode; | ||
592 | |||
593 | ACPI_FUNCTION_TRACE("acpi_pcc_write_keyinput"); | ||
594 | |||
595 | if (!hotkey || (count > (sizeof(write_string) - 1))) | ||
596 | return_VALUE(-EINVAL); | ||
597 | |||
598 | if (copy_from_user(write_string, buffer, count)) | ||
599 | return_VALUE(-EFAULT); | ||
600 | |||
601 | write_string[count] = '\0'; | ||
602 | |||
603 | if ((sscanf(write_string, "%4i", &key_mode) == 1) && | ||
604 | (key_mode == 0 || key_mode == 1)) { | ||
605 | keyinput = input_get_drvdata(hotkey->input_dev); | ||
606 | keyinput->key_mode = key_mode; | ||
607 | } | ||
608 | |||
609 | return_VALUE(count); | ||
610 | } | ||
611 | |||
612 | /* ------------------------------------------------------------------------- | ||
613 | hotkey driver | ||
614 | ------------------------------------------------------------------------- */ | ||
615 | static void acpi_pcc_generete_keyinput(struct acpi_hotkey *hotkey) | ||
616 | { | ||
617 | struct input_dev *hotk_input_dev = hotkey->input_dev; | ||
618 | struct pcc_keyinput *keyinput = input_get_drvdata(hotk_input_dev); | ||
619 | int hinf = hotkey->status; | ||
620 | int key_code, hkey_num; | ||
621 | const int key_map[] = { | ||
622 | /* 0 */ -1, | ||
623 | /* 1 */ KEY_BRIGHTNESSDOWN, | ||
624 | /* 2 */ KEY_BRIGHTNESSUP, | ||
625 | /* 3 */ -1, /* vga/lcd switch event is not occur on | ||
626 | hotkey driver. */ | ||
627 | /* 4 */ KEY_MUTE, | ||
628 | /* 5 */ KEY_VOLUMEDOWN, | ||
629 | /* 6 */ KEY_VOLUMEUP, | ||
630 | /* 7 */ KEY_SLEEP, | ||
631 | /* 8 */ -1, /* Change CPU boost: do nothing */ | ||
632 | /* 9 */ KEY_BATT, | ||
633 | /* 10 */ KEY_SUSPEND, | ||
634 | }; | ||
635 | |||
636 | ACPI_FUNCTION_TRACE("acpi_pcc_generete_keyinput"); | ||
637 | |||
638 | if (keyinput->key_mode == 0) | ||
639 | return_VOID; | ||
640 | |||
641 | hkey_num = hinf & 0xf; | ||
642 | |||
643 | if ((0 > hkey_num) || | ||
644 | (hkey_num > ARRAY_SIZE(key_map))) { | ||
645 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
646 | "hotkey number out of range: %d\n", | ||
647 | hkey_num)); | ||
648 | return_VOID; | ||
649 | } | ||
650 | |||
651 | key_code = key_map[hkey_num]; | ||
652 | |||
653 | if (key_code != -1) { | ||
654 | int pushed = (hinf & 0x80) ? TRUE : FALSE; | ||
655 | |||
656 | input_report_key(hotk_input_dev, key_code, pushed); | ||
657 | input_sync(hotk_input_dev); | ||
658 | } | ||
659 | } | ||
660 | |||
661 | static int acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey) | ||
662 | { | ||
663 | unsigned long result; | ||
664 | acpi_status status = AE_OK; | ||
665 | |||
666 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_get_key"); | ||
667 | |||
668 | status = acpi_evaluate_integer(hotkey->handle, METHOD_HKEY_QUERY, | ||
669 | NULL, &result); | ||
670 | if (likely(ACPI_SUCCESS(status))) | ||
671 | hotkey->status = result; | ||
672 | else | ||
673 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
674 | "error getting hotkey status\n")); | ||
675 | |||
676 | return_VALUE(status == AE_OK); | ||
677 | } | ||
678 | |||
679 | void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) | ||
680 | { | ||
681 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *) data; | ||
682 | |||
683 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_notify"); | ||
684 | |||
685 | switch (event) { | ||
686 | case HKEY_NOTIFY: | ||
687 | if (acpi_pcc_hotkey_get_key(hotkey)) { | ||
688 | /* generate event like '"pcc HKEY 00000080 00000084"' | ||
689 | * when Fn+F4 pressed */ | ||
690 | acpi_bus_generate_proc_event(hotkey->device, event, | ||
691 | hotkey->status); | ||
692 | } | ||
693 | acpi_pcc_generete_keyinput(hotkey); | ||
694 | break; | ||
695 | default: | ||
696 | /* nothing to do */ | ||
697 | break; | ||
698 | } | ||
699 | return_VOID; | ||
700 | } | ||
701 | |||
702 | /* ************************************************************************* | ||
703 | FS Interface (/proc) | ||
704 | ************************************************************************* */ | ||
705 | /* oepn proc file fs*/ | ||
706 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_open_fs, acpi_pcc_dc_brightness_show); | ||
707 | SEQ_OPEN_FS(acpi_pcc_numbatteries_open_fs, acpi_pcc_numbatteries_show); | ||
708 | SEQ_OPEN_FS(acpi_pcc_lcdtype_open_fs, acpi_pcc_lcdtype_show); | ||
709 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_max_open_fs, | ||
710 | acpi_pcc_ac_brightness_max_show); | ||
711 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_min_open_fs, | ||
712 | acpi_pcc_ac_brightness_min_show); | ||
713 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_open_fs, acpi_pcc_ac_brightness_show); | ||
714 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_max_open_fs, | ||
715 | acpi_pcc_dc_brightness_max_show); | ||
716 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_min_open_fs, | ||
717 | acpi_pcc_dc_brightness_min_show); | ||
718 | SEQ_OPEN_FS(acpi_pcc_brightness_open_fs, acpi_pcc_brightness_show); | ||
719 | SEQ_OPEN_FS(acpi_pcc_mute_open_fs, acpi_pcc_mute_show); | ||
720 | SEQ_OPEN_FS(acpi_pcc_version_open_fs, acpi_pcc_version_show); | ||
721 | SEQ_OPEN_FS(acpi_pcc_keyinput_open_fs, acpi_pcc_keyinput_show); | ||
722 | SEQ_OPEN_FS(acpi_pcc_sticky_key_open_fs, acpi_pcc_sticky_key_show); | ||
723 | |||
724 | static struct file_operations acpi_pcc_numbatteries_fops = | ||
725 | SEQ_FILEOPS_R(acpi_pcc_numbatteries_open_fs); | ||
726 | static struct file_operations acpi_pcc_lcdtype_fops = | ||
727 | SEQ_FILEOPS_R(acpi_pcc_lcdtype_open_fs); | ||
728 | static struct file_operations acpi_pcc_mute_fops = | ||
729 | SEQ_FILEOPS_RW(acpi_pcc_mute_open_fs, acpi_pcc_write_mute); | ||
730 | static struct file_operations acpi_pcc_ac_brightness_fops = | ||
731 | SEQ_FILEOPS_RW(acpi_pcc_ac_brightness_open_fs, | ||
732 | acpi_pcc_write_ac_brightness); | ||
733 | static struct file_operations acpi_pcc_ac_brightness_max_fops = | ||
734 | SEQ_FILEOPS_R(acpi_pcc_ac_brightness_max_open_fs); | ||
735 | static struct file_operations acpi_pcc_ac_brightness_min_fops = | ||
736 | SEQ_FILEOPS_R(acpi_pcc_ac_brightness_min_open_fs); | ||
737 | static struct file_operations acpi_pcc_dc_brightness_fops = | ||
738 | SEQ_FILEOPS_RW(acpi_pcc_dc_brightness_open_fs, | ||
739 | acpi_pcc_write_dc_brightness); | ||
740 | static struct file_operations acpi_pcc_dc_brightness_max_fops = | ||
741 | SEQ_FILEOPS_R(acpi_pcc_dc_brightness_max_open_fs); | ||
742 | static struct file_operations acpi_pcc_dc_brightness_min_fops = | ||
743 | SEQ_FILEOPS_R(acpi_pcc_dc_brightness_min_open_fs); | ||
744 | static struct file_operations acpi_pcc_brightness_fops = | ||
745 | SEQ_FILEOPS_RW(acpi_pcc_brightness_open_fs, | ||
746 | acpi_pcc_write_no_brightness); | ||
747 | static struct file_operations acpi_pcc_sticky_key_fops = | ||
748 | SEQ_FILEOPS_RW(acpi_pcc_sticky_key_open_fs, acpi_pcc_write_sticky_key); | ||
749 | static struct file_operations acpi_pcc_keyinput_fops = | ||
750 | SEQ_FILEOPS_RW(acpi_pcc_keyinput_open_fs, acpi_pcc_write_keyinput); | ||
751 | static struct file_operations acpi_pcc_version_fops = | ||
752 | SEQ_FILEOPS_R(acpi_pcc_version_open_fs); | ||
753 | |||
754 | struct proc_item { | ||
755 | const char *name; | ||
756 | struct file_operations *fops; | ||
757 | mode_t flag; | ||
758 | }; | ||
759 | |||
760 | /* Note: These functions map *exactly* to the SINF/SSET functions */ | ||
761 | struct proc_item acpi_pcc_proc_items_sifr[] = { | ||
762 | { "num_batteries", &acpi_pcc_numbatteries_fops, S_IRUGO }, | ||
763 | { "lcd_type", &acpi_pcc_lcdtype_fops, S_IRUGO }, | ||
764 | { "ac_brightness_max", &acpi_pcc_ac_brightness_max_fops, S_IRUGO }, | ||
765 | { "ac_brightness_min", &acpi_pcc_ac_brightness_min_fops, S_IRUGO }, | ||
766 | { "ac_brightness", &acpi_pcc_ac_brightness_fops, | ||
767 | S_IFREG | S_IRUGO | S_IWUSR }, | ||
768 | { "dc_brightness_max", &acpi_pcc_dc_brightness_max_fops, S_IRUGO }, | ||
769 | { "dc_brightness_min", &acpi_pcc_dc_brightness_min_fops, S_IRUGO }, | ||
770 | { "dc_brightness", &acpi_pcc_dc_brightness_fops, | ||
771 | S_IFREG | S_IRUGO | S_IWUSR }, | ||
772 | { "brightness", &acpi_pcc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR}, | ||
773 | { "mute", &acpi_pcc_mute_fops, S_IFREG | S_IRUGO | S_IWUSR }, | ||
774 | { NULL, NULL, 0 }, | ||
775 | }; | ||
776 | |||
777 | struct proc_item acpi_pcc_proc_items[] = { | ||
778 | { "sticky_key", &acpi_pcc_sticky_key_fops, S_IFREG | S_IRUGO | S_IWUSR}, | ||
779 | { "keyinput", &acpi_pcc_keyinput_fops, S_IFREG | S_IRUGO | S_IWUSR }, | ||
780 | { "version", &acpi_pcc_version_fops, S_IRUGO }, | ||
781 | { NULL, NULL, 0 }, | ||
782 | }; | ||
783 | |||
784 | static int __devinit acpi_pcc_add_device(struct acpi_device *device, | ||
785 | struct proc_item *proc_items, | ||
786 | int num) | ||
787 | { | ||
788 | struct acpi_hotkey *hotkey = acpi_driver_data(device); | ||
789 | struct proc_dir_entry *proc; | ||
790 | struct proc_item *item; | ||
791 | int i; | ||
792 | |||
793 | for (item = proc_items, i = 0; item->name && i < num; ++item, ++i) { | ||
794 | proc = create_proc_entry(item->name, item->flag, | ||
795 | hotkey->proc_dir_entry); | ||
796 | if (likely(proc)) { | ||
797 | proc->proc_fops = item->fops; | ||
798 | proc->data = hotkey; | ||
799 | proc->owner = THIS_MODULE; | ||
800 | } else { | ||
801 | while (i-- > 0) { | ||
802 | item--; | ||
803 | remove_proc_entry(item->name, | ||
804 | hotkey->proc_dir_entry); | ||
805 | } | ||
806 | return_VALUE(-ENODEV); | ||
807 | } | ||
808 | } | ||
809 | return_VALUE(0); | ||
810 | } | ||
811 | |||
812 | static int __devinit acpi_pcc_proc_init(struct acpi_device *device) | ||
813 | { | ||
814 | struct proc_dir_entry *acpi_pcc_dir; | ||
815 | struct acpi_hotkey *hotkey = acpi_driver_data(device); | ||
816 | acpi_status status; | ||
817 | |||
818 | ACPI_FUNCTION_TRACE("acpi_pcc_proc_init"); | ||
819 | |||
820 | acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir); | ||
821 | |||
822 | if (unlikely(!acpi_pcc_dir)) { | ||
823 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
824 | "Couldn't create dir in /proc\n")); | ||
825 | return_VALUE(-ENODEV); | ||
826 | } | ||
827 | |||
828 | acpi_pcc_dir->owner = THIS_MODULE; | ||
829 | hotkey->proc_dir_entry = acpi_pcc_dir; | ||
830 | |||
831 | status = acpi_pcc_add_device(device, acpi_pcc_proc_items_sifr, | ||
832 | hotkey->num_sifr); | ||
833 | status |= acpi_pcc_add_device(device, acpi_pcc_proc_items, | ||
834 | ARRAY_SIZE(acpi_pcc_proc_items)); | ||
835 | if (unlikely(status)) { | ||
836 | remove_proc_entry(PROC_PCC, acpi_root_dir); | ||
837 | hotkey->proc_dir_entry = NULL; | ||
838 | return_VALUE(-ENODEV); | ||
839 | } | ||
840 | |||
841 | return_VALUE(status); | ||
842 | } | ||
843 | |||
844 | static void __devexit acpi_pcc_remove_device(struct acpi_device *device, | ||
845 | struct proc_item *proc_items, | ||
846 | int num) | ||
847 | { | ||
848 | struct acpi_hotkey *hotkey = acpi_driver_data(device); | ||
849 | struct proc_item *item; | ||
850 | int i; | ||
851 | |||
852 | for (item = proc_items, i = 0; | ||
853 | item->name != NULL && i < num; | ||
854 | ++item, ++i) { | ||
855 | remove_proc_entry(item->name, hotkey->proc_dir_entry); | ||
856 | } | ||
857 | |||
858 | return_VOID; | ||
859 | } | ||
860 | |||
861 | /* ************************************************************************* | ||
862 | Power Management | ||
863 | ************************************************************************* */ | ||
864 | #ifdef CONFIG_PM | ||
865 | static int acpi_pcc_hotkey_resume(struct acpi_device *device) | ||
866 | { | ||
867 | struct acpi_hotkey *hotkey = acpi_driver_data(device); | ||
868 | acpi_status status = AE_OK; | ||
869 | |||
870 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume"); | ||
871 | |||
872 | if (device == NULL || hotkey == NULL) | ||
873 | return_VALUE(-EINVAL); | ||
874 | |||
875 | if (hotkey->num_sifr != 0) { | ||
876 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Sticky mode restore: %d\n", | ||
877 | hotkey->sticky_mode)); | ||
878 | |||
879 | status = acpi_pcc_write_sset(hotkey, SINF_STICKY_KEY, | ||
880 | hotkey->sticky_mode); | ||
881 | } | ||
882 | if (status != AE_OK) | ||
883 | return_VALUE(-EINVAL); | ||
884 | |||
885 | return_VALUE(0); | ||
886 | } | ||
887 | #endif | ||
888 | |||
889 | /* ************************************************************************* | ||
890 | Module init/remove | ||
891 | ************************************************************************* */ | ||
892 | /* ------------------------------------------------------------------------- | ||
893 | input | ||
894 | ------------------------------------------------------------------------- */ | ||
895 | static int __devinit acpi_pcc_init_input(struct acpi_hotkey *hotkey) | ||
896 | { | ||
897 | struct input_dev *hotk_input_dev; | ||
898 | struct pcc_keyinput *pcc_keyinput; | ||
899 | int error; | ||
900 | |||
901 | ACPI_FUNCTION_TRACE("acpi_pcc_init_input"); | ||
902 | |||
903 | hotk_input_dev = input_allocate_device(); | ||
904 | if (hotk_input_dev == NULL) { | ||
905 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
906 | "Couldn't allocate input device for hotkey")); | ||
907 | goto err_input; | ||
908 | } | ||
909 | |||
910 | pcc_keyinput = kcalloc(1, sizeof(struct pcc_keyinput), GFP_KERNEL); | ||
911 | |||
912 | if (pcc_keyinput == NULL) { | ||
913 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
914 | "Couldn't allocate mem for private data")); | ||
915 | goto err_pcc; | ||
916 | } | ||
917 | |||
918 | hotk_input_dev->evbit[0] = BIT(EV_KEY); | ||
919 | |||
920 | set_bit(KEY_BRIGHTNESSDOWN, hotk_input_dev->keybit); | ||
921 | set_bit(KEY_BRIGHTNESSUP, hotk_input_dev->keybit); | ||
922 | set_bit(KEY_MUTE, hotk_input_dev->keybit); | ||
923 | set_bit(KEY_VOLUMEDOWN, hotk_input_dev->keybit); | ||
924 | set_bit(KEY_VOLUMEUP, hotk_input_dev->keybit); | ||
925 | set_bit(KEY_SLEEP, hotk_input_dev->keybit); | ||
926 | set_bit(KEY_BATT, hotk_input_dev->keybit); | ||
927 | set_bit(KEY_SUSPEND, hotk_input_dev->keybit); | ||
928 | |||
929 | hotk_input_dev->name = ACPI_PCC_DRIVER_NAME; | ||
930 | hotk_input_dev->phys = ACPI_PCC_INPUT_PHYS; | ||
931 | hotk_input_dev->id.bustype = BUS_PCC_HOTKEY; | ||
932 | hotk_input_dev->id.vendor = 0x0001; | ||
933 | hotk_input_dev->id.product = 0x0001; | ||
934 | hotk_input_dev->id.version = 0x0100; | ||
935 | |||
936 | pcc_keyinput->key_mode = PCC_KEYINPUT_MODE; | ||
937 | pcc_keyinput->hotkey = hotkey; | ||
938 | |||
939 | input_set_drvdata(hotk_input_dev, pcc_keyinput); | ||
940 | |||
941 | hotkey->input_dev = hotk_input_dev; | ||
942 | |||
943 | error = input_register_device(hotk_input_dev); | ||
944 | |||
945 | if (error) | ||
946 | goto err_pcc; | ||
947 | |||
948 | return_VALUE(0); | ||
949 | |||
950 | err_pcc: | ||
951 | input_unregister_device(hotk_input_dev); | ||
952 | err_input: | ||
953 | return_VALUE(-ENOMEM); | ||
954 | } | ||
955 | |||
956 | static void __devexit acpi_pcc_remove_input(struct acpi_hotkey *hotkey) | ||
957 | { | ||
958 | struct input_dev *hotk_input_dev; | ||
959 | struct pcc_keyinput *pcc_keyinput; | ||
960 | |||
961 | ACPI_FUNCTION_TRACE("acpi_pcc_remove_input"); | ||
962 | |||
963 | if (hotkey == NULL) { | ||
964 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Can't free memory")); | ||
965 | return_VOID; | ||
966 | } | ||
967 | |||
968 | hotk_input_dev = hotkey->input_dev; | ||
969 | pcc_keyinput = input_get_drvdata(hotk_input_dev); | ||
970 | |||
971 | input_unregister_device(hotk_input_dev); | ||
972 | |||
973 | kfree(pcc_keyinput); | ||
974 | } | ||
975 | |||
976 | /* ------------------------------------------------------------------------- | ||
977 | ACPI | ||
978 | ------------------------------------------------------------------------- */ | ||
979 | static int __devinit acpi_pcc_hotkey_add(struct acpi_device *device) | ||
980 | { | ||
981 | acpi_status status = AE_OK; | ||
982 | struct acpi_hotkey *hotkey = NULL; | ||
983 | int sifr_status, num_sifr, result; | ||
984 | |||
985 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add"); | ||
986 | |||
987 | if (device == NULL) | ||
988 | return_VALUE(-EINVAL); | ||
989 | |||
990 | sifr_status = acpi_pcc_get_sqty(device); | ||
991 | |||
992 | if (sifr_status > 255) { | ||
993 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large")); | ||
994 | return_VALUE(-ENODEV); | ||
995 | } | ||
996 | |||
997 | if (sifr_status < 0) { | ||
998 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "not support SQTY")); | ||
999 | num_sifr = 0; | ||
1000 | } else { | ||
1001 | num_sifr = sifr_status; | ||
1002 | } | ||
1003 | |||
1004 | hotkey = kcalloc(1, sizeof(struct acpi_hotkey), GFP_KERNEL); | ||
1005 | if (hotkey == NULL) { | ||
1006 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
1007 | "Couldn't allocate mem for hotkey")); | ||
1008 | return_VALUE(-ENOMEM); | ||
1009 | } | ||
1010 | |||
1011 | hotkey->device = device; | ||
1012 | hotkey->handle = device->handle; | ||
1013 | hotkey->num_sifr = num_sifr; | ||
1014 | device->driver_data = hotkey; | ||
1015 | strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); | ||
1016 | strcpy(acpi_device_class(device), ACPI_PCC_CLASS); | ||
1017 | |||
1018 | status = acpi_install_notify_handler(hotkey->handle, | ||
1019 | ACPI_DEVICE_NOTIFY, | ||
1020 | acpi_pcc_hotkey_notify, | ||
1021 | hotkey); | ||
1022 | |||
1023 | if (ACPI_FAILURE(status)) { | ||
1024 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
1025 | "Error installing notify handler\n")); | ||
1026 | kfree(hotkey); | ||
1027 | return_VALUE(-ENODEV); | ||
1028 | } | ||
1029 | |||
1030 | result = acpi_pcc_init_input(hotkey); | ||
1031 | if (result != 0) { | ||
1032 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
1033 | "Error installing keyinput handler\n")); | ||
1034 | kfree(hotkey); | ||
1035 | return_VALUE(result); | ||
1036 | } | ||
1037 | |||
1038 | return_VALUE(acpi_pcc_proc_init(device)); | ||
1039 | } | ||
1040 | |||
1041 | static int __devexit acpi_pcc_hotkey_remove(struct acpi_device *device, | ||
1042 | int type) | ||
1043 | { | ||
1044 | acpi_status status = AE_OK; | ||
1045 | struct acpi_hotkey *hotkey = acpi_driver_data(device); | ||
1046 | |||
1047 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove"); | ||
1048 | |||
1049 | if (!device || !hotkey) | ||
1050 | return_VALUE(-EINVAL); | ||
1051 | |||
1052 | if (hotkey->proc_dir_entry) { | ||
1053 | acpi_pcc_remove_device(device, acpi_pcc_proc_items_sifr, | ||
1054 | hotkey->num_sifr); | ||
1055 | acpi_pcc_remove_device(device, acpi_pcc_proc_items, | ||
1056 | ARRAY_SIZE(acpi_pcc_proc_items)); | ||
1057 | remove_proc_entry(PROC_PCC, acpi_root_dir); | ||
1058 | } | ||
1059 | |||
1060 | status = acpi_remove_notify_handler(hotkey->handle, | ||
1061 | ACPI_DEVICE_NOTIFY, acpi_pcc_hotkey_notify); | ||
1062 | |||
1063 | if (ACPI_FAILURE(status)) { | ||
1064 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
1065 | "Error removing notify handler\n")); | ||
1066 | } | ||
1067 | |||
1068 | acpi_pcc_remove_input(hotkey); | ||
1069 | kfree(hotkey); | ||
1070 | return_VALUE(status == AE_OK); | ||
1071 | } | ||
1072 | |||
1073 | /* ********************************************************************* | ||
1074 | Module entry point | ||
1075 | ********************************************************************* */ | ||
1076 | static int __init acpi_pcc_init(void) | ||
1077 | { | ||
1078 | int result; | ||
1079 | |||
1080 | ACPI_FUNCTION_TRACE("acpi_pcc_init"); | ||
1081 | |||
1082 | printk(KERN_INFO LOGPREFIX "loading...\n"); | ||
1083 | |||
1084 | if (acpi_disabled) { | ||
1085 | printk(KERN_INFO LOGPREFIX "ACPI disabled.\n"); | ||
1086 | return_VALUE(-ENODEV); | ||
1087 | } | ||
1088 | |||
1089 | result = acpi_bus_register_driver(&acpi_pcc_driver); | ||
1090 | if (result < 0) { | ||
1091 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
1092 | "Error registering hotkey driver\n")); | ||
1093 | return_VALUE(-ENODEV); | ||
1094 | } | ||
1095 | |||
1096 | return_VALUE(result); | ||
1097 | } | ||
1098 | |||
1099 | static void __exit acpi_pcc_exit(void) | ||
1100 | { | ||
1101 | ACPI_FUNCTION_TRACE("acpi_pcc_exit"); | ||
1102 | |||
1103 | printk(KERN_INFO LOGPREFIX "unloading...\n"); | ||
1104 | |||
1105 | acpi_bus_unregister_driver(&acpi_pcc_driver); | ||
1106 | |||
1107 | return_VOID; | ||
1108 | } | ||
1109 | |||
1110 | module_init(acpi_pcc_init); | ||
1111 | module_exit(acpi_pcc_exit); | ||