]> Pileus Git - ~andy/linux/blob - drivers/platform/x86/sony-laptop.c
Merge commit '4cb38750d49010ae72e718d46605ac9ba5a851b4' into stable/for-linus-3.6
[~andy/linux] / drivers / platform / x86 / sony-laptop.c
1 /*
2  * ACPI Sony Notebook Control Driver (SNC and SPIC)
3  *
4  * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
5  * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it>
6  *
7  * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
8  * which are copyrighted by their respective authors.
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  *
29  * This program is free software; you can redistribute it and/or modify
30  * it under the terms of the GNU General Public License as published by
31  * the Free Software Foundation; either version 2 of the License, or
32  * (at your option) any later version.
33  *
34  * This program is distributed in the hope that it will be useful,
35  * but WITHOUT ANY WARRANTY; without even the implied warranty of
36  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37  * GNU General Public License for more details.
38  *
39  * You should have received a copy of the GNU General Public License
40  * along with this program; if not, write to the Free Software
41  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42  *
43  */
44
45 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
46
47 #include <linux/kernel.h>
48 #include <linux/module.h>
49 #include <linux/moduleparam.h>
50 #include <linux/init.h>
51 #include <linux/types.h>
52 #include <linux/backlight.h>
53 #include <linux/platform_device.h>
54 #include <linux/err.h>
55 #include <linux/dmi.h>
56 #include <linux/pci.h>
57 #include <linux/interrupt.h>
58 #include <linux/delay.h>
59 #include <linux/input.h>
60 #include <linux/kfifo.h>
61 #include <linux/workqueue.h>
62 #include <linux/acpi.h>
63 #include <linux/slab.h>
64 #include <acpi/acpi_drivers.h>
65 #include <acpi/acpi_bus.h>
66 #include <asm/uaccess.h>
67 #include <linux/sonypi.h>
68 #include <linux/sony-laptop.h>
69 #include <linux/rfkill.h>
70 #ifdef CONFIG_SONYPI_COMPAT
71 #include <linux/poll.h>
72 #include <linux/miscdevice.h>
73 #endif
74
75 #define dprintk(fmt, ...)                       \
76 do {                                            \
77         if (debug)                              \
78                 pr_warn(fmt, ##__VA_ARGS__);    \
79 } while (0)
80
81 #define SONY_LAPTOP_DRIVER_VERSION      "0.6"
82
83 #define SONY_NC_CLASS           "sony-nc"
84 #define SONY_NC_HID             "SNY5001"
85 #define SONY_NC_DRIVER_NAME     "Sony Notebook Control Driver"
86
87 #define SONY_PIC_CLASS          "sony-pic"
88 #define SONY_PIC_HID            "SNY6001"
89 #define SONY_PIC_DRIVER_NAME    "Sony Programmable IO Control Driver"
90
91 MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
92 MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)");
93 MODULE_LICENSE("GPL");
94 MODULE_VERSION(SONY_LAPTOP_DRIVER_VERSION);
95
96 static int debug;
97 module_param(debug, int, 0);
98 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
99                  "the development of this driver");
100
101 static int no_spic;             /* = 0 */
102 module_param(no_spic, int, 0444);
103 MODULE_PARM_DESC(no_spic,
104                  "set this if you don't want to enable the SPIC device");
105
106 static int compat;              /* = 0 */
107 module_param(compat, int, 0444);
108 MODULE_PARM_DESC(compat,
109                  "set this if you want to enable backward compatibility mode");
110
111 static unsigned long mask = 0xffffffff;
112 module_param(mask, ulong, 0644);
113 MODULE_PARM_DESC(mask,
114                  "set this to the mask of event you want to enable (see doc)");
115
116 static int camera;              /* = 0 */
117 module_param(camera, int, 0444);
118 MODULE_PARM_DESC(camera,
119                  "set this to 1 to enable Motion Eye camera controls "
120                  "(only use it if you have a C1VE or C1VN model)");
121
122 #ifdef CONFIG_SONYPI_COMPAT
123 static int minor = -1;
124 module_param(minor, int, 0);
125 MODULE_PARM_DESC(minor,
126                  "minor number of the misc device for the SPIC compatibility code, "
127                  "default is -1 (automatic)");
128 #endif
129
130 static int kbd_backlight = 1;
131 module_param(kbd_backlight, int, 0444);
132 MODULE_PARM_DESC(kbd_backlight,
133                  "set this to 0 to disable keyboard backlight, "
134                  "1 to enable it (default: 0)");
135
136 static int kbd_backlight_timeout;       /* = 0 */
137 module_param(kbd_backlight_timeout, int, 0444);
138 MODULE_PARM_DESC(kbd_backlight_timeout,
139                  "set this to 0 to set the default 10 seconds timeout, "
140                  "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
141                  "(default: 0)");
142
143 static void sony_nc_kbd_backlight_resume(void);
144 static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
145                 unsigned int handle);
146 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd);
147
148 static int sony_nc_battery_care_setup(struct platform_device *pd,
149                 unsigned int handle);
150 static void sony_nc_battery_care_cleanup(struct platform_device *pd);
151
152 static int sony_nc_thermal_setup(struct platform_device *pd);
153 static void sony_nc_thermal_cleanup(struct platform_device *pd);
154 static void sony_nc_thermal_resume(void);
155
156 static int sony_nc_lid_resume_setup(struct platform_device *pd);
157 static void sony_nc_lid_resume_cleanup(struct platform_device *pd);
158
159 static int sony_nc_highspeed_charging_setup(struct platform_device *pd);
160 static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd);
161
162 static int sony_nc_touchpad_setup(struct platform_device *pd,
163                                   unsigned int handle);
164 static void sony_nc_touchpad_cleanup(struct platform_device *pd);
165
166 enum sony_nc_rfkill {
167         SONY_WIFI,
168         SONY_BLUETOOTH,
169         SONY_WWAN,
170         SONY_WIMAX,
171         N_SONY_RFKILL,
172 };
173
174 static int sony_rfkill_handle;
175 static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
176 static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
177 static int sony_nc_rfkill_setup(struct acpi_device *device,
178                 unsigned int handle);
179 static void sony_nc_rfkill_cleanup(void);
180 static void sony_nc_rfkill_update(void);
181
182 /*********** Input Devices ***********/
183
184 #define SONY_LAPTOP_BUF_SIZE    128
185 struct sony_laptop_input_s {
186         atomic_t                users;
187         struct input_dev        *jog_dev;
188         struct input_dev        *key_dev;
189         struct kfifo            fifo;
190         spinlock_t              fifo_lock;
191         struct timer_list       release_key_timer;
192 };
193
194 static struct sony_laptop_input_s sony_laptop_input = {
195         .users = ATOMIC_INIT(0),
196 };
197
198 struct sony_laptop_keypress {
199         struct input_dev *dev;
200         int key;
201 };
202
203 /* Correspondance table between sonypi events
204  * and input layer indexes in the keymap
205  */
206 static int sony_laptop_input_index[] = {
207         -1,     /*  0 no event */
208         -1,     /*  1 SONYPI_EVENT_JOGDIAL_DOWN */
209         -1,     /*  2 SONYPI_EVENT_JOGDIAL_UP */
210         -1,     /*  3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */
211         -1,     /*  4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */
212         -1,     /*  5 SONYPI_EVENT_JOGDIAL_PRESSED */
213         -1,     /*  6 SONYPI_EVENT_JOGDIAL_RELEASED */
214          0,     /*  7 SONYPI_EVENT_CAPTURE_PRESSED */
215          1,     /*  8 SONYPI_EVENT_CAPTURE_RELEASED */
216          2,     /*  9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
217          3,     /* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
218          4,     /* 11 SONYPI_EVENT_FNKEY_ESC */
219          5,     /* 12 SONYPI_EVENT_FNKEY_F1 */
220          6,     /* 13 SONYPI_EVENT_FNKEY_F2 */
221          7,     /* 14 SONYPI_EVENT_FNKEY_F3 */
222          8,     /* 15 SONYPI_EVENT_FNKEY_F4 */
223          9,     /* 16 SONYPI_EVENT_FNKEY_F5 */
224         10,     /* 17 SONYPI_EVENT_FNKEY_F6 */
225         11,     /* 18 SONYPI_EVENT_FNKEY_F7 */
226         12,     /* 19 SONYPI_EVENT_FNKEY_F8 */
227         13,     /* 20 SONYPI_EVENT_FNKEY_F9 */
228         14,     /* 21 SONYPI_EVENT_FNKEY_F10 */
229         15,     /* 22 SONYPI_EVENT_FNKEY_F11 */
230         16,     /* 23 SONYPI_EVENT_FNKEY_F12 */
231         17,     /* 24 SONYPI_EVENT_FNKEY_1 */
232         18,     /* 25 SONYPI_EVENT_FNKEY_2 */
233         19,     /* 26 SONYPI_EVENT_FNKEY_D */
234         20,     /* 27 SONYPI_EVENT_FNKEY_E */
235         21,     /* 28 SONYPI_EVENT_FNKEY_F */
236         22,     /* 29 SONYPI_EVENT_FNKEY_S */
237         23,     /* 30 SONYPI_EVENT_FNKEY_B */
238         24,     /* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */
239         25,     /* 32 SONYPI_EVENT_PKEY_P1 */
240         26,     /* 33 SONYPI_EVENT_PKEY_P2 */
241         27,     /* 34 SONYPI_EVENT_PKEY_P3 */
242         28,     /* 35 SONYPI_EVENT_BACK_PRESSED */
243         -1,     /* 36 SONYPI_EVENT_LID_CLOSED */
244         -1,     /* 37 SONYPI_EVENT_LID_OPENED */
245         29,     /* 38 SONYPI_EVENT_BLUETOOTH_ON */
246         30,     /* 39 SONYPI_EVENT_BLUETOOTH_OFF */
247         31,     /* 40 SONYPI_EVENT_HELP_PRESSED */
248         32,     /* 41 SONYPI_EVENT_FNKEY_ONLY */
249         33,     /* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */
250         34,     /* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */
251         35,     /* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
252         36,     /* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
253         37,     /* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
254         38,     /* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */
255         39,     /* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
256         40,     /* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
257         41,     /* 50 SONYPI_EVENT_ZOOM_PRESSED */
258         42,     /* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */
259         43,     /* 52 SONYPI_EVENT_MEYE_FACE */
260         44,     /* 53 SONYPI_EVENT_MEYE_OPPOSITE */
261         45,     /* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */
262         46,     /* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */
263         -1,     /* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */
264         -1,     /* 57 SONYPI_EVENT_BATTERY_INSERT */
265         -1,     /* 58 SONYPI_EVENT_BATTERY_REMOVE */
266         -1,     /* 59 SONYPI_EVENT_FNKEY_RELEASED */
267         47,     /* 60 SONYPI_EVENT_WIRELESS_ON */
268         48,     /* 61 SONYPI_EVENT_WIRELESS_OFF */
269         49,     /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */
270         50,     /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */
271         51,     /* 64 SONYPI_EVENT_CD_EJECT_PRESSED */
272         52,     /* 65 SONYPI_EVENT_MODEKEY_PRESSED */
273         53,     /* 66 SONYPI_EVENT_PKEY_P4 */
274         54,     /* 67 SONYPI_EVENT_PKEY_P5 */
275         55,     /* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */
276         56,     /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */
277         57,     /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
278         -1,     /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
279         58,     /* 72 SONYPI_EVENT_MEDIA_PRESSED */
280         59,     /* 72 SONYPI_EVENT_VENDOR_PRESSED */
281 };
282
283 static int sony_laptop_input_keycode_map[] = {
284         KEY_CAMERA,     /*  0 SONYPI_EVENT_CAPTURE_PRESSED */
285         KEY_RESERVED,   /*  1 SONYPI_EVENT_CAPTURE_RELEASED */
286         KEY_RESERVED,   /*  2 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
287         KEY_RESERVED,   /*  3 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
288         KEY_FN_ESC,     /*  4 SONYPI_EVENT_FNKEY_ESC */
289         KEY_FN_F1,      /*  5 SONYPI_EVENT_FNKEY_F1 */
290         KEY_FN_F2,      /*  6 SONYPI_EVENT_FNKEY_F2 */
291         KEY_FN_F3,      /*  7 SONYPI_EVENT_FNKEY_F3 */
292         KEY_FN_F4,      /*  8 SONYPI_EVENT_FNKEY_F4 */
293         KEY_FN_F5,      /*  9 SONYPI_EVENT_FNKEY_F5 */
294         KEY_FN_F6,      /* 10 SONYPI_EVENT_FNKEY_F6 */
295         KEY_FN_F7,      /* 11 SONYPI_EVENT_FNKEY_F7 */
296         KEY_FN_F8,      /* 12 SONYPI_EVENT_FNKEY_F8 */
297         KEY_FN_F9,      /* 13 SONYPI_EVENT_FNKEY_F9 */
298         KEY_FN_F10,     /* 14 SONYPI_EVENT_FNKEY_F10 */
299         KEY_FN_F11,     /* 15 SONYPI_EVENT_FNKEY_F11 */
300         KEY_FN_F12,     /* 16 SONYPI_EVENT_FNKEY_F12 */
301         KEY_FN_F1,      /* 17 SONYPI_EVENT_FNKEY_1 */
302         KEY_FN_F2,      /* 18 SONYPI_EVENT_FNKEY_2 */
303         KEY_FN_D,       /* 19 SONYPI_EVENT_FNKEY_D */
304         KEY_FN_E,       /* 20 SONYPI_EVENT_FNKEY_E */
305         KEY_FN_F,       /* 21 SONYPI_EVENT_FNKEY_F */
306         KEY_FN_S,       /* 22 SONYPI_EVENT_FNKEY_S */
307         KEY_FN_B,       /* 23 SONYPI_EVENT_FNKEY_B */
308         KEY_BLUETOOTH,  /* 24 SONYPI_EVENT_BLUETOOTH_PRESSED */
309         KEY_PROG1,      /* 25 SONYPI_EVENT_PKEY_P1 */
310         KEY_PROG2,      /* 26 SONYPI_EVENT_PKEY_P2 */
311         KEY_PROG3,      /* 27 SONYPI_EVENT_PKEY_P3 */
312         KEY_BACK,       /* 28 SONYPI_EVENT_BACK_PRESSED */
313         KEY_BLUETOOTH,  /* 29 SONYPI_EVENT_BLUETOOTH_ON */
314         KEY_BLUETOOTH,  /* 30 SONYPI_EVENT_BLUETOOTH_OFF */
315         KEY_HELP,       /* 31 SONYPI_EVENT_HELP_PRESSED */
316         KEY_FN,         /* 32 SONYPI_EVENT_FNKEY_ONLY */
317         KEY_RESERVED,   /* 33 SONYPI_EVENT_JOGDIAL_FAST_DOWN */
318         KEY_RESERVED,   /* 34 SONYPI_EVENT_JOGDIAL_FAST_UP */
319         KEY_RESERVED,   /* 35 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
320         KEY_RESERVED,   /* 36 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
321         KEY_RESERVED,   /* 37 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
322         KEY_RESERVED,   /* 38 SONYPI_EVENT_JOGDIAL_VFAST_UP */
323         KEY_RESERVED,   /* 39 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
324         KEY_RESERVED,   /* 40 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
325         KEY_ZOOM,       /* 41 SONYPI_EVENT_ZOOM_PRESSED */
326         BTN_THUMB,      /* 42 SONYPI_EVENT_THUMBPHRASE_PRESSED */
327         KEY_RESERVED,   /* 43 SONYPI_EVENT_MEYE_FACE */
328         KEY_RESERVED,   /* 44 SONYPI_EVENT_MEYE_OPPOSITE */
329         KEY_RESERVED,   /* 45 SONYPI_EVENT_MEMORYSTICK_INSERT */
330         KEY_RESERVED,   /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */
331         KEY_WLAN,       /* 47 SONYPI_EVENT_WIRELESS_ON */
332         KEY_WLAN,       /* 48 SONYPI_EVENT_WIRELESS_OFF */
333         KEY_ZOOMIN,     /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */
334         KEY_ZOOMOUT,    /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */
335         KEY_EJECTCD,    /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */
336         KEY_F13,        /* 52 SONYPI_EVENT_MODEKEY_PRESSED */
337         KEY_PROG4,      /* 53 SONYPI_EVENT_PKEY_P4 */
338         KEY_F14,        /* 54 SONYPI_EVENT_PKEY_P5 */
339         KEY_F15,        /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */
340         KEY_VOLUMEUP,   /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
341         KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
342         KEY_MEDIA,      /* 58 SONYPI_EVENT_MEDIA_PRESSED */
343         KEY_VENDOR,     /* 59 SONYPI_EVENT_VENDOR_PRESSED */
344 };
345
346 /* release buttons after a short delay if pressed */
347 static void do_sony_laptop_release_key(unsigned long unused)
348 {
349         struct sony_laptop_keypress kp;
350         unsigned long flags;
351
352         spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags);
353
354         if (kfifo_out(&sony_laptop_input.fifo,
355                       (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
356                 input_report_key(kp.dev, kp.key, 0);
357                 input_sync(kp.dev);
358         }
359
360         /* If there is something in the fifo schedule next release. */
361         if (kfifo_len(&sony_laptop_input.fifo) != 0)
362                 mod_timer(&sony_laptop_input.release_key_timer,
363                           jiffies + msecs_to_jiffies(10));
364
365         spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags);
366 }
367
368 /* forward event to the input subsystem */
369 static void sony_laptop_report_input_event(u8 event)
370 {
371         struct input_dev *jog_dev = sony_laptop_input.jog_dev;
372         struct input_dev *key_dev = sony_laptop_input.key_dev;
373         struct sony_laptop_keypress kp = { NULL };
374         int scancode = -1;
375
376         if (event == SONYPI_EVENT_FNKEY_RELEASED ||
377                         event == SONYPI_EVENT_ANYBUTTON_RELEASED) {
378                 /* Nothing, not all VAIOs generate this event */
379                 return;
380         }
381
382         /* report events */
383         switch (event) {
384         /* jog_dev events */
385         case SONYPI_EVENT_JOGDIAL_UP:
386         case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
387                 input_report_rel(jog_dev, REL_WHEEL, 1);
388                 input_sync(jog_dev);
389                 return;
390
391         case SONYPI_EVENT_JOGDIAL_DOWN:
392         case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
393                 input_report_rel(jog_dev, REL_WHEEL, -1);
394                 input_sync(jog_dev);
395                 return;
396
397         /* key_dev events */
398         case SONYPI_EVENT_JOGDIAL_PRESSED:
399                 kp.key = BTN_MIDDLE;
400                 kp.dev = jog_dev;
401                 break;
402
403         default:
404                 if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
405                         dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
406                         break;
407                 }
408                 if ((scancode = sony_laptop_input_index[event]) != -1) {
409                         kp.key = sony_laptop_input_keycode_map[scancode];
410                         if (kp.key != KEY_UNKNOWN)
411                                 kp.dev = key_dev;
412                 }
413                 break;
414         }
415
416         if (kp.dev) {
417                 /* if we have a scancode we emit it so we can always
418                     remap the key */
419                 if (scancode != -1)
420                         input_event(kp.dev, EV_MSC, MSC_SCAN, scancode);
421                 input_report_key(kp.dev, kp.key, 1);
422                 input_sync(kp.dev);
423
424                 /* schedule key release */
425                 kfifo_in_locked(&sony_laptop_input.fifo,
426                                 (unsigned char *)&kp, sizeof(kp),
427                                 &sony_laptop_input.fifo_lock);
428                 mod_timer(&sony_laptop_input.release_key_timer,
429                           jiffies + msecs_to_jiffies(10));
430         } else
431                 dprintk("unknown input event %.2x\n", event);
432 }
433
434 static int sony_laptop_setup_input(struct acpi_device *acpi_device)
435 {
436         struct input_dev *jog_dev;
437         struct input_dev *key_dev;
438         int i;
439         int error;
440
441         /* don't run again if already initialized */
442         if (atomic_add_return(1, &sony_laptop_input.users) > 1)
443                 return 0;
444
445         /* kfifo */
446         spin_lock_init(&sony_laptop_input.fifo_lock);
447         error = kfifo_alloc(&sony_laptop_input.fifo,
448                             SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
449         if (error) {
450                 pr_err("kfifo_alloc failed\n");
451                 goto err_dec_users;
452         }
453
454         setup_timer(&sony_laptop_input.release_key_timer,
455                     do_sony_laptop_release_key, 0);
456
457         /* input keys */
458         key_dev = input_allocate_device();
459         if (!key_dev) {
460                 error = -ENOMEM;
461                 goto err_free_kfifo;
462         }
463
464         key_dev->name = "Sony Vaio Keys";
465         key_dev->id.bustype = BUS_ISA;
466         key_dev->id.vendor = PCI_VENDOR_ID_SONY;
467         key_dev->dev.parent = &acpi_device->dev;
468
469         /* Initialize the Input Drivers: special keys */
470         input_set_capability(key_dev, EV_MSC, MSC_SCAN);
471
472         __set_bit(EV_KEY, key_dev->evbit);
473         key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
474         key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
475         key_dev->keycode = &sony_laptop_input_keycode_map;
476         for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++)
477                 __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
478         __clear_bit(KEY_RESERVED, key_dev->keybit);
479
480         error = input_register_device(key_dev);
481         if (error)
482                 goto err_free_keydev;
483
484         sony_laptop_input.key_dev = key_dev;
485
486         /* jogdial */
487         jog_dev = input_allocate_device();
488         if (!jog_dev) {
489                 error = -ENOMEM;
490                 goto err_unregister_keydev;
491         }
492
493         jog_dev->name = "Sony Vaio Jogdial";
494         jog_dev->id.bustype = BUS_ISA;
495         jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
496         jog_dev->dev.parent = &acpi_device->dev;
497
498         input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
499         input_set_capability(jog_dev, EV_REL, REL_WHEEL);
500
501         error = input_register_device(jog_dev);
502         if (error)
503                 goto err_free_jogdev;
504
505         sony_laptop_input.jog_dev = jog_dev;
506
507         return 0;
508
509 err_free_jogdev:
510         input_free_device(jog_dev);
511
512 err_unregister_keydev:
513         input_unregister_device(key_dev);
514         /* to avoid kref underflow below at input_free_device */
515         key_dev = NULL;
516
517 err_free_keydev:
518         input_free_device(key_dev);
519
520 err_free_kfifo:
521         kfifo_free(&sony_laptop_input.fifo);
522
523 err_dec_users:
524         atomic_dec(&sony_laptop_input.users);
525         return error;
526 }
527
528 static void sony_laptop_remove_input(void)
529 {
530         struct sony_laptop_keypress kp = { NULL };
531
532         /* Cleanup only after the last user has gone */
533         if (!atomic_dec_and_test(&sony_laptop_input.users))
534                 return;
535
536         del_timer_sync(&sony_laptop_input.release_key_timer);
537
538         /*
539          * Generate key-up events for remaining keys. Note that we don't
540          * need locking since nobody is adding new events to the kfifo.
541          */
542         while (kfifo_out(&sony_laptop_input.fifo,
543                          (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
544                 input_report_key(kp.dev, kp.key, 0);
545                 input_sync(kp.dev);
546         }
547
548         /* destroy input devs */
549         input_unregister_device(sony_laptop_input.key_dev);
550         sony_laptop_input.key_dev = NULL;
551
552         if (sony_laptop_input.jog_dev) {
553                 input_unregister_device(sony_laptop_input.jog_dev);
554                 sony_laptop_input.jog_dev = NULL;
555         }
556
557         kfifo_free(&sony_laptop_input.fifo);
558 }
559
560 /*********** Platform Device ***********/
561
562 static atomic_t sony_pf_users = ATOMIC_INIT(0);
563 static struct platform_driver sony_pf_driver = {
564         .driver = {
565                    .name = "sony-laptop",
566                    .owner = THIS_MODULE,
567                    }
568 };
569 static struct platform_device *sony_pf_device;
570
571 static int sony_pf_add(void)
572 {
573         int ret = 0;
574
575         /* don't run again if already initialized */
576         if (atomic_add_return(1, &sony_pf_users) > 1)
577                 return 0;
578
579         ret = platform_driver_register(&sony_pf_driver);
580         if (ret)
581                 goto out;
582
583         sony_pf_device = platform_device_alloc("sony-laptop", -1);
584         if (!sony_pf_device) {
585                 ret = -ENOMEM;
586                 goto out_platform_registered;
587         }
588
589         ret = platform_device_add(sony_pf_device);
590         if (ret)
591                 goto out_platform_alloced;
592
593         return 0;
594
595       out_platform_alloced:
596         platform_device_put(sony_pf_device);
597         sony_pf_device = NULL;
598       out_platform_registered:
599         platform_driver_unregister(&sony_pf_driver);
600       out:
601         atomic_dec(&sony_pf_users);
602         return ret;
603 }
604
605 static void sony_pf_remove(void)
606 {
607         /* deregister only after the last user has gone */
608         if (!atomic_dec_and_test(&sony_pf_users))
609                 return;
610
611         platform_device_unregister(sony_pf_device);
612         platform_driver_unregister(&sony_pf_driver);
613 }
614
615 /*********** SNC (SNY5001) Device ***********/
616
617 /* the device uses 1-based values, while the backlight subsystem uses
618    0-based values */
619 #define SONY_MAX_BRIGHTNESS     8
620
621 #define SNC_VALIDATE_IN         0
622 #define SNC_VALIDATE_OUT        1
623
624 static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
625                               char *);
626 static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
627                                const char *, size_t);
628 static int boolean_validate(const int, const int);
629 static int brightness_default_validate(const int, const int);
630
631 struct sony_nc_value {
632         char *name;             /* name of the entry */
633         char **acpiget;         /* names of the ACPI get function */
634         char **acpiset;         /* names of the ACPI set function */
635         int (*validate)(const int, const int);  /* input/output validation */
636         int value;              /* current setting */
637         int valid;              /* Has ever been set */
638         int debug;              /* active only in debug mode ? */
639         struct device_attribute devattr;        /* sysfs attribute */
640 };
641
642 #define SNC_HANDLE_NAMES(_name, _values...) \
643         static char *snc_##_name[] = { _values, NULL }
644
645 #define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \
646         { \
647                 .name           = __stringify(_name), \
648                 .acpiget        = _getters, \
649                 .acpiset        = _setters, \
650                 .validate       = _validate, \
651                 .debug          = _debug, \
652                 .devattr        = __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \
653         }
654
655 #define SNC_HANDLE_NULL { .name = NULL }
656
657 SNC_HANDLE_NAMES(fnkey_get, "GHKE");
658
659 SNC_HANDLE_NAMES(brightness_def_get, "GPBR");
660 SNC_HANDLE_NAMES(brightness_def_set, "SPBR");
661
662 SNC_HANDLE_NAMES(cdpower_get, "GCDP");
663 SNC_HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
664
665 SNC_HANDLE_NAMES(audiopower_get, "GAZP");
666 SNC_HANDLE_NAMES(audiopower_set, "AZPW");
667
668 SNC_HANDLE_NAMES(lanpower_get, "GLNP");
669 SNC_HANDLE_NAMES(lanpower_set, "LNPW");
670
671 SNC_HANDLE_NAMES(lidstate_get, "GLID");
672
673 SNC_HANDLE_NAMES(indicatorlamp_get, "GILS");
674 SNC_HANDLE_NAMES(indicatorlamp_set, "SILS");
675
676 SNC_HANDLE_NAMES(gainbass_get, "GMGB");
677 SNC_HANDLE_NAMES(gainbass_set, "CMGB");
678
679 SNC_HANDLE_NAMES(PID_get, "GPID");
680
681 SNC_HANDLE_NAMES(CTR_get, "GCTR");
682 SNC_HANDLE_NAMES(CTR_set, "SCTR");
683
684 SNC_HANDLE_NAMES(PCR_get, "GPCR");
685 SNC_HANDLE_NAMES(PCR_set, "SPCR");
686
687 SNC_HANDLE_NAMES(CMI_get, "GCMI");
688 SNC_HANDLE_NAMES(CMI_set, "SCMI");
689
690 static struct sony_nc_value sony_nc_values[] = {
691         SNC_HANDLE(brightness_default, snc_brightness_def_get,
692                         snc_brightness_def_set, brightness_default_validate, 0),
693         SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
694         SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
695         SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
696                         boolean_validate, 0),
697         SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
698                         boolean_validate, 1),
699         SNC_HANDLE(lidstate, snc_lidstate_get, NULL,
700                         boolean_validate, 0),
701         SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set,
702                         boolean_validate, 0),
703         SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set,
704                         boolean_validate, 0),
705         /* unknown methods */
706         SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1),
707         SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
708         SNC_HANDLE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
709         SNC_HANDLE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
710         SNC_HANDLE_NULL
711 };
712
713 static acpi_handle sony_nc_acpi_handle;
714 static struct acpi_device *sony_nc_acpi_device = NULL;
715
716 /*
717  * acpi_evaluate_object wrappers
718  * all useful calls into SNC methods take one or zero parameters and return
719  * integers or arrays.
720  */
721 static union acpi_object *__call_snc_method(acpi_handle handle, char *method,
722                 u64 *value)
723 {
724         union acpi_object *result = NULL;
725         struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
726         acpi_status status;
727
728         if (value) {
729                 struct acpi_object_list params;
730                 union acpi_object in;
731                 in.type = ACPI_TYPE_INTEGER;
732                 in.integer.value = *value;
733                 params.count = 1;
734                 params.pointer = &in;
735                 status = acpi_evaluate_object(handle, method, &params, &output);
736                 dprintk("__call_snc_method: [%s:0x%.8x%.8x]\n", method,
737                                 (unsigned int)(*value >> 32),
738                                 (unsigned int)*value & 0xffffffff);
739         } else {
740                 status = acpi_evaluate_object(handle, method, NULL, &output);
741                 dprintk("__call_snc_method: [%s]\n", method);
742         }
743
744         if (ACPI_FAILURE(status)) {
745                 pr_err("Failed to evaluate [%s]\n", method);
746                 return NULL;
747         }
748
749         result = (union acpi_object *) output.pointer;
750         if (!result)
751                 dprintk("No return object [%s]\n", method);
752
753         return result;
754 }
755
756 static int sony_nc_int_call(acpi_handle handle, char *name, int *value,
757                 int *result)
758 {
759         union acpi_object *object = NULL;
760         if (value) {
761                 u64 v = *value;
762                 object = __call_snc_method(handle, name, &v);
763         } else
764                 object = __call_snc_method(handle, name, NULL);
765
766         if (!object)
767                 return -EINVAL;
768
769         if (object->type != ACPI_TYPE_INTEGER) {
770                 pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n",
771                                 ACPI_TYPE_INTEGER, object->type);
772                 kfree(object);
773                 return -EINVAL;
774         }
775
776         if (result)
777                 *result = object->integer.value;
778
779         kfree(object);
780         return 0;
781 }
782
783 #define MIN(a, b)       (a > b ? b : a)
784 static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
785                 void *buffer, size_t buflen)
786 {
787         size_t len = len;
788         union acpi_object *object = __call_snc_method(handle, name, value);
789
790         if (!object)
791                 return -EINVAL;
792
793         if (object->type == ACPI_TYPE_BUFFER)
794                 len = MIN(buflen, object->buffer.length);
795
796         else if (object->type == ACPI_TYPE_INTEGER)
797                 len = MIN(buflen, sizeof(object->integer.value));
798
799         else {
800                 pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n",
801                                 ACPI_TYPE_BUFFER, object->type);
802                 kfree(object);
803                 return -EINVAL;
804         }
805
806         memcpy(buffer, object->buffer.pointer, len);
807         kfree(object);
808         return 0;
809 }
810
811 struct sony_nc_handles {
812         u16 cap[0x10];
813         struct device_attribute devattr;
814 };
815
816 static struct sony_nc_handles *handles;
817
818 static ssize_t sony_nc_handles_show(struct device *dev,
819                 struct device_attribute *attr, char *buffer)
820 {
821         ssize_t len = 0;
822         int i;
823
824         for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
825                 len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
826                                 handles->cap[i]);
827         }
828         len += snprintf(buffer + len, PAGE_SIZE - len, "\n");
829
830         return len;
831 }
832
833 static int sony_nc_handles_setup(struct platform_device *pd)
834 {
835         int i, r, result, arg;
836
837         handles = kzalloc(sizeof(*handles), GFP_KERNEL);
838         if (!handles)
839                 return -ENOMEM;
840
841         for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
842                 arg = i + 0x20;
843                 r = sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg,
844                                         &result);
845                 if (!r) {
846                         dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
847                                         result, i);
848                         handles->cap[i] = result;
849                 }
850         }
851
852         if (debug) {
853                 sysfs_attr_init(&handles->devattr.attr);
854                 handles->devattr.attr.name = "handles";
855                 handles->devattr.attr.mode = S_IRUGO;
856                 handles->devattr.show = sony_nc_handles_show;
857
858                 /* allow reading capabilities via sysfs */
859                 if (device_create_file(&pd->dev, &handles->devattr)) {
860                         kfree(handles);
861                         handles = NULL;
862                         return -1;
863                 }
864         }
865
866         return 0;
867 }
868
869 static int sony_nc_handles_cleanup(struct platform_device *pd)
870 {
871         if (handles) {
872                 if (debug)
873                         device_remove_file(&pd->dev, &handles->devattr);
874                 kfree(handles);
875                 handles = NULL;
876         }
877         return 0;
878 }
879
880 static int sony_find_snc_handle(int handle)
881 {
882         int i;
883
884         /* not initialized yet, return early */
885         if (!handles || !handle)
886                 return -EINVAL;
887
888         for (i = 0; i < 0x10; i++) {
889                 if (handles->cap[i] == handle) {
890                         dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
891                                         handle, i);
892                         return i;
893                 }
894         }
895         dprintk("handle 0x%.4x not found\n", handle);
896         return -EINVAL;
897 }
898
899 static int sony_call_snc_handle(int handle, int argument, int *result)
900 {
901         int arg, ret = 0;
902         int offset = sony_find_snc_handle(handle);
903
904         if (offset < 0)
905                 return offset;
906
907         arg = offset | argument;
908         ret = sony_nc_int_call(sony_nc_acpi_handle, "SN07", &arg, result);
909         dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", arg, *result);
910         return ret;
911 }
912
913 /*
914  * sony_nc_values input/output validate functions
915  */
916
917 /* brightness_default_validate:
918  *
919  * manipulate input output values to keep consistency with the
920  * backlight framework for which brightness values are 0-based.
921  */
922 static int brightness_default_validate(const int direction, const int value)
923 {
924         switch (direction) {
925                 case SNC_VALIDATE_OUT:
926                         return value - 1;
927                 case SNC_VALIDATE_IN:
928                         if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
929                                 return value + 1;
930         }
931         return -EINVAL;
932 }
933
934 /* boolean_validate:
935  *
936  * on input validate boolean values 0/1, on output just pass the
937  * received value.
938  */
939 static int boolean_validate(const int direction, const int value)
940 {
941         if (direction == SNC_VALIDATE_IN) {
942                 if (value != 0 && value != 1)
943                         return -EINVAL;
944         }
945         return value;
946 }
947
948 /*
949  * Sysfs show/store common to all sony_nc_values
950  */
951 static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
952                               char *buffer)
953 {
954         int value, ret = 0;
955         struct sony_nc_value *item =
956             container_of(attr, struct sony_nc_value, devattr);
957
958         if (!*item->acpiget)
959                 return -EIO;
960
961         ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiget, NULL,
962                                 &value);
963         if (ret < 0)
964                 return -EIO;
965
966         if (item->validate)
967                 value = item->validate(SNC_VALIDATE_OUT, value);
968
969         return snprintf(buffer, PAGE_SIZE, "%d\n", value);
970 }
971
972 static ssize_t sony_nc_sysfs_store(struct device *dev,
973                                struct device_attribute *attr,
974                                const char *buffer, size_t count)
975 {
976         int value;
977         int ret = 0;
978         struct sony_nc_value *item =
979             container_of(attr, struct sony_nc_value, devattr);
980
981         if (!item->acpiset)
982                 return -EIO;
983
984         if (count > 31)
985                 return -EINVAL;
986
987         if (kstrtoint(buffer, 10, &value))
988                 return -EINVAL;
989
990         if (item->validate)
991                 value = item->validate(SNC_VALIDATE_IN, value);
992
993         if (value < 0)
994                 return value;
995
996         ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset,
997                                &value, NULL);
998         if (ret < 0)
999                 return -EIO;
1000
1001         item->value = value;
1002         item->valid = 1;
1003         return count;
1004 }
1005
1006
1007 /*
1008  * Backlight device
1009  */
1010 struct sony_backlight_props {
1011         struct backlight_device *dev;
1012         int                     handle;
1013         int                     cmd_base;
1014         u8                      offset;
1015         u8                      maxlvl;
1016 };
1017 struct sony_backlight_props sony_bl_props;
1018
1019 static int sony_backlight_update_status(struct backlight_device *bd)
1020 {
1021         int arg = bd->props.brightness + 1;
1022         return sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &arg, NULL);
1023 }
1024
1025 static int sony_backlight_get_brightness(struct backlight_device *bd)
1026 {
1027         int value;
1028
1029         if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL, &value))
1030                 return 0;
1031         /* brightness levels are 1-based, while backlight ones are 0-based */
1032         return value - 1;
1033 }
1034
1035 static int sony_nc_get_brightness_ng(struct backlight_device *bd)
1036 {
1037         int result;
1038         struct sony_backlight_props *sdev =
1039                 (struct sony_backlight_props *)bl_get_data(bd);
1040
1041         sony_call_snc_handle(sdev->handle, sdev->cmd_base + 0x100, &result);
1042
1043         return (result & 0xff) - sdev->offset;
1044 }
1045
1046 static int sony_nc_update_status_ng(struct backlight_device *bd)
1047 {
1048         int value, result;
1049         struct sony_backlight_props *sdev =
1050                 (struct sony_backlight_props *)bl_get_data(bd);
1051
1052         value = bd->props.brightness + sdev->offset;
1053         if (sony_call_snc_handle(sdev->handle, sdev->cmd_base | (value << 0x10),
1054                                 &result))
1055                 return -EIO;
1056
1057         return value;
1058 }
1059
1060 static const struct backlight_ops sony_backlight_ops = {
1061         .options = BL_CORE_SUSPENDRESUME,
1062         .update_status = sony_backlight_update_status,
1063         .get_brightness = sony_backlight_get_brightness,
1064 };
1065 static const struct backlight_ops sony_backlight_ng_ops = {
1066         .options = BL_CORE_SUSPENDRESUME,
1067         .update_status = sony_nc_update_status_ng,
1068         .get_brightness = sony_nc_get_brightness_ng,
1069 };
1070
1071 /*
1072  * New SNC-only Vaios event mapping to driver known keys
1073  */
1074 struct sony_nc_event {
1075         u8      data;
1076         u8      event;
1077 };
1078
1079 static struct sony_nc_event sony_100_events[] = {
1080         { 0x90, SONYPI_EVENT_PKEY_P1 },
1081         { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
1082         { 0x91, SONYPI_EVENT_PKEY_P2 },
1083         { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
1084         { 0x81, SONYPI_EVENT_FNKEY_F1 },
1085         { 0x01, SONYPI_EVENT_FNKEY_RELEASED },
1086         { 0x82, SONYPI_EVENT_FNKEY_F2 },
1087         { 0x02, SONYPI_EVENT_FNKEY_RELEASED },
1088         { 0x83, SONYPI_EVENT_FNKEY_F3 },
1089         { 0x03, SONYPI_EVENT_FNKEY_RELEASED },
1090         { 0x84, SONYPI_EVENT_FNKEY_F4 },
1091         { 0x04, SONYPI_EVENT_FNKEY_RELEASED },
1092         { 0x85, SONYPI_EVENT_FNKEY_F5 },
1093         { 0x05, SONYPI_EVENT_FNKEY_RELEASED },
1094         { 0x86, SONYPI_EVENT_FNKEY_F6 },
1095         { 0x06, SONYPI_EVENT_FNKEY_RELEASED },
1096         { 0x87, SONYPI_EVENT_FNKEY_F7 },
1097         { 0x07, SONYPI_EVENT_FNKEY_RELEASED },
1098         { 0x88, SONYPI_EVENT_FNKEY_F8 },
1099         { 0x08, SONYPI_EVENT_FNKEY_RELEASED },
1100         { 0x89, SONYPI_EVENT_FNKEY_F9 },
1101         { 0x09, SONYPI_EVENT_FNKEY_RELEASED },
1102         { 0x8A, SONYPI_EVENT_FNKEY_F10 },
1103         { 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
1104         { 0x8B, SONYPI_EVENT_FNKEY_F11 },
1105         { 0x0B, SONYPI_EVENT_FNKEY_RELEASED },
1106         { 0x8C, SONYPI_EVENT_FNKEY_F12 },
1107         { 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
1108         { 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
1109         { 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
1110         { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
1111         { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
1112         { 0xa1, SONYPI_EVENT_MEDIA_PRESSED },
1113         { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED },
1114         { 0xa4, SONYPI_EVENT_CD_EJECT_PRESSED },
1115         { 0x24, SONYPI_EVENT_ANYBUTTON_RELEASED },
1116         { 0xa5, SONYPI_EVENT_VENDOR_PRESSED },
1117         { 0x25, SONYPI_EVENT_ANYBUTTON_RELEASED },
1118         { 0xa6, SONYPI_EVENT_HELP_PRESSED },
1119         { 0x26, SONYPI_EVENT_ANYBUTTON_RELEASED },
1120         { 0, 0 },
1121 };
1122
1123 static struct sony_nc_event sony_127_events[] = {
1124         { 0x81, SONYPI_EVENT_MODEKEY_PRESSED },
1125         { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED },
1126         { 0x82, SONYPI_EVENT_PKEY_P1 },
1127         { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED },
1128         { 0x83, SONYPI_EVENT_PKEY_P2 },
1129         { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED },
1130         { 0x84, SONYPI_EVENT_PKEY_P3 },
1131         { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED },
1132         { 0x85, SONYPI_EVENT_PKEY_P4 },
1133         { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
1134         { 0x86, SONYPI_EVENT_PKEY_P5 },
1135         { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
1136         { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
1137         { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
1138         { 0, 0 },
1139 };
1140
1141 static int sony_nc_hotkeys_decode(u32 event, unsigned int handle)
1142 {
1143         int ret = -EINVAL;
1144         unsigned int result = 0;
1145         struct sony_nc_event *key_event;
1146
1147         if (sony_call_snc_handle(handle, 0x200, &result)) {
1148                 dprintk("Unable to decode event 0x%.2x 0x%.2x\n", handle,
1149                                 event);
1150                 return -EINVAL;
1151         }
1152
1153         result &= 0xFF;
1154
1155         if (handle == 0x0100)
1156                 key_event = sony_100_events;
1157         else
1158                 key_event = sony_127_events;
1159
1160         for (; key_event->data; key_event++) {
1161                 if (key_event->data == result) {
1162                         ret = key_event->event;
1163                         break;
1164                 }
1165         }
1166
1167         if (!key_event->data)
1168                 pr_info("Unknown hotkey 0x%.2x/0x%.2x (handle 0x%.2x)\n",
1169                                 event, result, handle);
1170
1171         return ret;
1172 }
1173
1174 /*
1175  * ACPI callbacks
1176  */
1177 enum event_types {
1178         HOTKEY = 1,
1179         KILLSWITCH,
1180         GFX_SWITCH
1181 };
1182 static void sony_nc_notify(struct acpi_device *device, u32 event)
1183 {
1184         u32 real_ev = event;
1185         u8 ev_type = 0;
1186         dprintk("sony_nc_notify, event: 0x%.2x\n", event);
1187
1188         if (event >= 0x90) {
1189                 unsigned int result = 0;
1190                 unsigned int arg = 0;
1191                 unsigned int handle = 0;
1192                 unsigned int offset = event - 0x90;
1193
1194                 if (offset >= ARRAY_SIZE(handles->cap)) {
1195                         pr_err("Event 0x%x outside of capabilities list\n",
1196                                         event);
1197                         return;
1198                 }
1199                 handle = handles->cap[offset];
1200
1201                 /* list of handles known for generating events */
1202                 switch (handle) {
1203                 /* hotkey event */
1204                 case 0x0100:
1205                 case 0x0127:
1206                         ev_type = HOTKEY;
1207                         real_ev = sony_nc_hotkeys_decode(event, handle);
1208
1209                         if (real_ev > 0)
1210                                 sony_laptop_report_input_event(real_ev);
1211                         else
1212                                 /* restore the original event for reporting */
1213                                 real_ev = event;
1214
1215                         break;
1216
1217                 /* wlan switch */
1218                 case 0x0124:
1219                 case 0x0135:
1220                         /* events on this handle are reported when the
1221                          * switch changes position or for battery
1222                          * events. We'll notify both of them but only
1223                          * update the rfkill device status when the
1224                          * switch is moved.
1225                          */
1226                         ev_type = KILLSWITCH;
1227                         sony_call_snc_handle(handle, 0x0100, &result);
1228                         real_ev = result & 0x03;
1229
1230                         /* hw switch event */
1231                         if (real_ev == 1)
1232                                 sony_nc_rfkill_update();
1233
1234                         break;
1235
1236                 case 0x0128:
1237                 case 0x0146:
1238                         /* Hybrid GFX switching */
1239                         sony_call_snc_handle(handle, 0x0000, &result);
1240                         dprintk("GFX switch event received (reason: %s)\n",
1241                                         (result & 0x01) ?
1242                                         "switch change" : "unknown");
1243
1244                         /* verify the switch state
1245                          * 1: discrete GFX
1246                          * 0: integrated GFX
1247                          */
1248                         sony_call_snc_handle(handle, 0x0100, &result);
1249
1250                         ev_type = GFX_SWITCH;
1251                         real_ev = result & 0xff;
1252                         break;
1253
1254                 default:
1255                         dprintk("Unknown event 0x%x for handle 0x%x\n",
1256                                         event, handle);
1257                         break;
1258                 }
1259
1260                 /* clear the event (and the event reason when present) */
1261                 arg = 1 << offset;
1262                 sony_nc_int_call(sony_nc_acpi_handle, "SN05", &arg, &result);
1263
1264         } else {
1265                 /* old style event */
1266                 ev_type = HOTKEY;
1267                 sony_laptop_report_input_event(real_ev);
1268         }
1269
1270         acpi_bus_generate_proc_event(sony_nc_acpi_device, ev_type, real_ev);
1271
1272         acpi_bus_generate_netlink_event(sony_nc_acpi_device->pnp.device_class,
1273                         dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev);
1274 }
1275
1276 static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
1277                                       void *context, void **return_value)
1278 {
1279         struct acpi_device_info *info;
1280
1281         if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
1282                 pr_warn("method: name: %4.4s, args %X\n",
1283                         (char *)&info->name, info->param_count);
1284
1285                 kfree(info);
1286         }
1287
1288         return AE_OK;
1289 }
1290
1291 /*
1292  * ACPI device
1293  */
1294 static void sony_nc_function_setup(struct acpi_device *device,
1295                 struct platform_device *pf_device)
1296 {
1297         unsigned int i, result, bitmask, arg;
1298
1299         if (!handles)
1300                 return;
1301
1302         /* setup found handles here */
1303         for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
1304                 unsigned int handle = handles->cap[i];
1305
1306                 if (!handle)
1307                         continue;
1308
1309                 dprintk("setting up handle 0x%.4x\n", handle);
1310
1311                 switch (handle) {
1312                 case 0x0100:
1313                 case 0x0101:
1314                 case 0x0127:
1315                         /* setup hotkeys */
1316                         sony_call_snc_handle(handle, 0, &result);
1317                         break;
1318                 case 0x0102:
1319                         /* setup hotkeys */
1320                         sony_call_snc_handle(handle, 0x100, &result);
1321                         break;
1322                 case 0x0105:
1323                 case 0x0148:
1324                         /* touchpad enable/disable */
1325                         result = sony_nc_touchpad_setup(pf_device, handle);
1326                         if (result)
1327                                 pr_err("couldn't set up touchpad control function (%d)\n",
1328                                                 result);
1329                         break;
1330                 case 0x0115:
1331                 case 0x0136:
1332                 case 0x013f:
1333                         result = sony_nc_battery_care_setup(pf_device, handle);
1334                         if (result)
1335                                 pr_err("couldn't set up battery care function (%d)\n",
1336                                                 result);
1337                         break;
1338                 case 0x0119:
1339                         result = sony_nc_lid_resume_setup(pf_device);
1340                         if (result)
1341                                 pr_err("couldn't set up lid resume function (%d)\n",
1342                                                 result);
1343                         break;
1344                 case 0x0122:
1345                         result = sony_nc_thermal_setup(pf_device);
1346                         if (result)
1347                                 pr_err("couldn't set up thermal profile function (%d)\n",
1348                                                 result);
1349                         break;
1350                 case 0x0131:
1351                         result = sony_nc_highspeed_charging_setup(pf_device);
1352                         if (result)
1353                                 pr_err("couldn't set up high speed charging function (%d)\n",
1354                                        result);
1355                         break;
1356                 case 0x0124:
1357                 case 0x0135:
1358                         result = sony_nc_rfkill_setup(device, handle);
1359                         if (result)
1360                                 pr_err("couldn't set up rfkill support (%d)\n",
1361                                                 result);
1362                         break;
1363                 case 0x0137:
1364                 case 0x0143:
1365                         result = sony_nc_kbd_backlight_setup(pf_device, handle);
1366                         if (result)
1367                                 pr_err("couldn't set up keyboard backlight function (%d)\n",
1368                                                 result);
1369                         break;
1370                 default:
1371                         continue;
1372                 }
1373         }
1374
1375         /* Enable all events */
1376         arg = 0x10;
1377         if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask))
1378                 sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask,
1379                                 &result);
1380 }
1381
1382 static void sony_nc_function_cleanup(struct platform_device *pd)
1383 {
1384         unsigned int i, result, bitmask, handle;
1385
1386         /* get enabled events and disable them */
1387         sony_nc_int_call(sony_nc_acpi_handle, "SN01", NULL, &bitmask);
1388         sony_nc_int_call(sony_nc_acpi_handle, "SN03", &bitmask, &result);
1389
1390         /* cleanup handles here */
1391         for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
1392
1393                 handle = handles->cap[i];
1394
1395                 if (!handle)
1396                         continue;
1397
1398                 switch (handle) {
1399                 case 0x0105:
1400                 case 0x0148:
1401                         sony_nc_touchpad_cleanup(pd);
1402                         break;
1403                 case 0x0115:
1404                 case 0x0136:
1405                 case 0x013f:
1406                         sony_nc_battery_care_cleanup(pd);
1407                         break;
1408                 case 0x0119:
1409                         sony_nc_lid_resume_cleanup(pd);
1410                         break;
1411                 case 0x0122:
1412                         sony_nc_thermal_cleanup(pd);
1413                         break;
1414                 case 0x0131:
1415                         sony_nc_highspeed_charging_cleanup(pd);
1416                         break;
1417                 case 0x0124:
1418                 case 0x0135:
1419                         sony_nc_rfkill_cleanup();
1420                         break;
1421                 case 0x0137:
1422                 case 0x0143:
1423                         sony_nc_kbd_backlight_cleanup(pd);
1424                         break;
1425                 default:
1426                         continue;
1427                 }
1428         }
1429
1430         /* finally cleanup the handles list */
1431         sony_nc_handles_cleanup(pd);
1432 }
1433
1434 static void sony_nc_function_resume(void)
1435 {
1436         unsigned int i, result, bitmask, arg;
1437
1438         dprintk("Resuming SNC device\n");
1439
1440         for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
1441                 unsigned int handle = handles->cap[i];
1442
1443                 if (!handle)
1444                         continue;
1445
1446                 switch (handle) {
1447                 case 0x0100:
1448                 case 0x0101:
1449                 case 0x0127:
1450                         /* re-enable hotkeys */
1451                         sony_call_snc_handle(handle, 0, &result);
1452                         break;
1453                 case 0x0102:
1454                         /* re-enable hotkeys */
1455                         sony_call_snc_handle(handle, 0x100, &result);
1456                         break;
1457                 case 0x0122:
1458                         sony_nc_thermal_resume();
1459                         break;
1460                 case 0x0124:
1461                 case 0x0135:
1462                         sony_nc_rfkill_update();
1463                         break;
1464                 case 0x0137:
1465                 case 0x0143:
1466                         sony_nc_kbd_backlight_resume();
1467                         break;
1468                 default:
1469                         continue;
1470                 }
1471         }
1472
1473         /* Enable all events */
1474         arg = 0x10;
1475         if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask))
1476                 sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask,
1477                                 &result);
1478 }
1479
1480 static int sony_nc_resume(struct device *dev)
1481 {
1482         struct sony_nc_value *item;
1483         acpi_handle handle;
1484
1485         for (item = sony_nc_values; item->name; item++) {
1486                 int ret;
1487
1488                 if (!item->valid)
1489                         continue;
1490                 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset,
1491                                        &item->value, NULL);
1492                 if (ret < 0) {
1493                         pr_err("%s: %d\n", __func__, ret);
1494                         break;
1495                 }
1496         }
1497
1498         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
1499                                          &handle))) {
1500                 int arg = 1;
1501                 if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
1502                         dprintk("ECON Method failed\n");
1503         }
1504
1505         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1506                                          &handle)))
1507                 sony_nc_function_resume();
1508
1509         return 0;
1510 }
1511
1512 static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume);
1513
1514 static void sony_nc_rfkill_cleanup(void)
1515 {
1516         int i;
1517
1518         for (i = 0; i < N_SONY_RFKILL; i++) {
1519                 if (sony_rfkill_devices[i]) {
1520                         rfkill_unregister(sony_rfkill_devices[i]);
1521                         rfkill_destroy(sony_rfkill_devices[i]);
1522                 }
1523         }
1524 }
1525
1526 static int sony_nc_rfkill_set(void *data, bool blocked)
1527 {
1528         int result;
1529         int argument = sony_rfkill_address[(long) data] + 0x100;
1530
1531         if (!blocked)
1532                 argument |= 0x030000;
1533
1534         return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1535 }
1536
1537 static const struct rfkill_ops sony_rfkill_ops = {
1538         .set_block = sony_nc_rfkill_set,
1539 };
1540
1541 static int sony_nc_setup_rfkill(struct acpi_device *device,
1542                                 enum sony_nc_rfkill nc_type)
1543 {
1544         int err = 0;
1545         struct rfkill *rfk;
1546         enum rfkill_type type;
1547         const char *name;
1548         int result;
1549         bool hwblock, swblock;
1550
1551         switch (nc_type) {
1552         case SONY_WIFI:
1553                 type = RFKILL_TYPE_WLAN;
1554                 name = "sony-wifi";
1555                 break;
1556         case SONY_BLUETOOTH:
1557                 type = RFKILL_TYPE_BLUETOOTH;
1558                 name = "sony-bluetooth";
1559                 break;
1560         case SONY_WWAN:
1561                 type = RFKILL_TYPE_WWAN;
1562                 name = "sony-wwan";
1563                 break;
1564         case SONY_WIMAX:
1565                 type = RFKILL_TYPE_WIMAX;
1566                 name = "sony-wimax";
1567                 break;
1568         default:
1569                 return -EINVAL;
1570         }
1571
1572         rfk = rfkill_alloc(name, &device->dev, type,
1573                            &sony_rfkill_ops, (void *)nc_type);
1574         if (!rfk)
1575                 return -ENOMEM;
1576
1577         if (sony_call_snc_handle(sony_rfkill_handle, 0x200, &result) < 0) {
1578                 rfkill_destroy(rfk);
1579                 return -1;
1580         }
1581         hwblock = !(result & 0x1);
1582
1583         if (sony_call_snc_handle(sony_rfkill_handle,
1584                                 sony_rfkill_address[nc_type],
1585                                 &result) < 0) {
1586                 rfkill_destroy(rfk);
1587                 return -1;
1588         }
1589         swblock = !(result & 0x2);
1590
1591         rfkill_init_sw_state(rfk, swblock);
1592         rfkill_set_hw_state(rfk, hwblock);
1593
1594         err = rfkill_register(rfk);
1595         if (err) {
1596                 rfkill_destroy(rfk);
1597                 return err;
1598         }
1599         sony_rfkill_devices[nc_type] = rfk;
1600         return err;
1601 }
1602
1603 static void sony_nc_rfkill_update(void)
1604 {
1605         enum sony_nc_rfkill i;
1606         int result;
1607         bool hwblock;
1608
1609         sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1610         hwblock = !(result & 0x1);
1611
1612         for (i = 0; i < N_SONY_RFKILL; i++) {
1613                 int argument = sony_rfkill_address[i];
1614
1615                 if (!sony_rfkill_devices[i])
1616                         continue;
1617
1618                 if (hwblock) {
1619                         if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
1620                                 /* we already know we're blocked */
1621                         }
1622                         continue;
1623                 }
1624
1625                 sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1626                 rfkill_set_states(sony_rfkill_devices[i],
1627                                   !(result & 0x2), false);
1628         }
1629 }
1630
1631 static int sony_nc_rfkill_setup(struct acpi_device *device,
1632                 unsigned int handle)
1633 {
1634         u64 offset;
1635         int i;
1636         unsigned char buffer[32] = { 0 };
1637
1638         offset = sony_find_snc_handle(handle);
1639         sony_rfkill_handle = handle;
1640
1641         i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer,
1642                         32);
1643         if (i < 0)
1644                 return i;
1645
1646         /* The buffer is filled with magic numbers describing the devices
1647          * available, 0xff terminates the enumeration.
1648          * Known codes:
1649          *      0x00 WLAN
1650          *      0x10 BLUETOOTH
1651          *      0x20 WWAN GPRS-EDGE
1652          *      0x21 WWAN HSDPA
1653          *      0x22 WWAN EV-DO
1654          *      0x23 WWAN GPS
1655          *      0x25 Gobi WWAN no GPS
1656          *      0x26 Gobi WWAN + GPS
1657          *      0x28 Gobi WWAN no GPS
1658          *      0x29 Gobi WWAN + GPS
1659          *      0x30 WIMAX
1660          *      0x50 Gobi WWAN no GPS
1661          *      0x51 Gobi WWAN + GPS
1662          *      0x70 no SIM card slot
1663          *      0x71 SIM card slot
1664          */
1665         for (i = 0; i < ARRAY_SIZE(buffer); i++) {
1666
1667                 if (buffer[i] == 0xff)
1668                         break;
1669
1670                 dprintk("Radio devices, found 0x%.2x\n", buffer[i]);
1671
1672                 if (buffer[i] == 0 && !sony_rfkill_devices[SONY_WIFI])
1673                         sony_nc_setup_rfkill(device, SONY_WIFI);
1674
1675                 if (buffer[i] == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
1676                         sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1677
1678                 if (((0xf0 & buffer[i]) == 0x20 ||
1679                                         (0xf0 & buffer[i]) == 0x50) &&
1680                                 !sony_rfkill_devices[SONY_WWAN])
1681                         sony_nc_setup_rfkill(device, SONY_WWAN);
1682
1683                 if (buffer[i] == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
1684                         sony_nc_setup_rfkill(device, SONY_WIMAX);
1685         }
1686         return 0;
1687 }
1688
1689 /* Keyboard backlight feature */
1690 struct kbd_backlight {
1691         unsigned int handle;
1692         unsigned int base;
1693         unsigned int mode;
1694         unsigned int timeout;
1695         struct device_attribute mode_attr;
1696         struct device_attribute timeout_attr;
1697 };
1698
1699 static struct kbd_backlight *kbdbl_ctl;
1700
1701 static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
1702 {
1703         int result;
1704
1705         if (value > 1)
1706                 return -EINVAL;
1707
1708         if (sony_call_snc_handle(kbdbl_ctl->handle,
1709                                 (value << 0x10) | (kbdbl_ctl->base), &result))
1710                 return -EIO;
1711
1712         /* Try to turn the light on/off immediately */
1713         sony_call_snc_handle(kbdbl_ctl->handle,
1714                         (value << 0x10) | (kbdbl_ctl->base + 0x100), &result);
1715
1716         kbdbl_ctl->mode = value;
1717
1718         return 0;
1719 }
1720
1721 static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
1722                 struct device_attribute *attr,
1723                 const char *buffer, size_t count)
1724 {
1725         int ret = 0;
1726         unsigned long value;
1727
1728         if (count > 31)
1729                 return -EINVAL;
1730
1731         if (kstrtoul(buffer, 10, &value))
1732                 return -EINVAL;
1733
1734         ret = __sony_nc_kbd_backlight_mode_set(value);
1735         if (ret < 0)
1736                 return ret;
1737
1738         return count;
1739 }
1740
1741 static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
1742                 struct device_attribute *attr, char *buffer)
1743 {
1744         ssize_t count = 0;
1745         count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->mode);
1746         return count;
1747 }
1748
1749 static int __sony_nc_kbd_backlight_timeout_set(u8 value)
1750 {
1751         int result;
1752
1753         if (value > 3)
1754                 return -EINVAL;
1755
1756         if (sony_call_snc_handle(kbdbl_ctl->handle, (value << 0x10) |
1757                                 (kbdbl_ctl->base + 0x200), &result))
1758                 return -EIO;
1759
1760         kbdbl_ctl->timeout = value;
1761
1762         return 0;
1763 }
1764
1765 static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
1766                 struct device_attribute *attr,
1767                 const char *buffer, size_t count)
1768 {
1769         int ret = 0;
1770         unsigned long value;
1771
1772         if (count > 31)
1773                 return -EINVAL;
1774
1775         if (kstrtoul(buffer, 10, &value))
1776                 return -EINVAL;
1777
1778         ret = __sony_nc_kbd_backlight_timeout_set(value);
1779         if (ret < 0)
1780                 return ret;
1781
1782         return count;
1783 }
1784
1785 static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
1786                 struct device_attribute *attr, char *buffer)
1787 {
1788         ssize_t count = 0;
1789         count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->timeout);
1790         return count;
1791 }
1792
1793 static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
1794                 unsigned int handle)
1795 {
1796         int result;
1797         int ret = 0;
1798
1799         /* verify the kbd backlight presence, these handles are not used for
1800          * keyboard backlight only
1801          */
1802         ret = sony_call_snc_handle(handle, handle == 0x0137 ? 0x0B00 : 0x0100,
1803                         &result);
1804         if (ret)
1805                 return ret;
1806
1807         if ((handle == 0x0137 && !(result & 0x02)) ||
1808                         !(result & 0x01)) {
1809                 dprintk("no backlight keyboard found\n");
1810                 return 0;
1811         }
1812
1813         kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL);
1814         if (!kbdbl_ctl)
1815                 return -ENOMEM;
1816
1817         kbdbl_ctl->handle = handle;
1818         if (handle == 0x0137)
1819                 kbdbl_ctl->base = 0x0C00;
1820         else
1821                 kbdbl_ctl->base = 0x4000;
1822
1823         sysfs_attr_init(&kbdbl_ctl->mode_attr.attr);
1824         kbdbl_ctl->mode_attr.attr.name = "kbd_backlight";
1825         kbdbl_ctl->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
1826         kbdbl_ctl->mode_attr.show = sony_nc_kbd_backlight_mode_show;
1827         kbdbl_ctl->mode_attr.store = sony_nc_kbd_backlight_mode_store;
1828
1829         sysfs_attr_init(&kbdbl_ctl->timeout_attr.attr);
1830         kbdbl_ctl->timeout_attr.attr.name = "kbd_backlight_timeout";
1831         kbdbl_ctl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
1832         kbdbl_ctl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
1833         kbdbl_ctl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
1834
1835         ret = device_create_file(&pd->dev, &kbdbl_ctl->mode_attr);
1836         if (ret)
1837                 goto outkzalloc;
1838
1839         ret = device_create_file(&pd->dev, &kbdbl_ctl->timeout_attr);
1840         if (ret)
1841                 goto outmode;
1842
1843         __sony_nc_kbd_backlight_mode_set(kbd_backlight);
1844         __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
1845
1846         return 0;
1847
1848 outmode:
1849         device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
1850 outkzalloc:
1851         kfree(kbdbl_ctl);
1852         kbdbl_ctl = NULL;
1853         return ret;
1854 }
1855
1856 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
1857 {
1858         if (kbdbl_ctl) {
1859                 int result;
1860
1861                 device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
1862                 device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr);
1863
1864                 /* restore the default hw behaviour */
1865                 sony_call_snc_handle(kbdbl_ctl->handle,
1866                                 kbdbl_ctl->base | 0x10000, &result);
1867                 sony_call_snc_handle(kbdbl_ctl->handle,
1868                                 kbdbl_ctl->base + 0x200, &result);
1869
1870                 kfree(kbdbl_ctl);
1871                 kbdbl_ctl = NULL;
1872         }
1873 }
1874
1875 static void sony_nc_kbd_backlight_resume(void)
1876 {
1877         int ignore = 0;
1878
1879         if (!kbdbl_ctl)
1880                 return;
1881
1882         if (kbdbl_ctl->mode == 0)
1883                 sony_call_snc_handle(kbdbl_ctl->handle, kbdbl_ctl->base,
1884                                 &ignore);
1885
1886         if (kbdbl_ctl->timeout != 0)
1887                 sony_call_snc_handle(kbdbl_ctl->handle,
1888                                 (kbdbl_ctl->base + 0x200) |
1889                                 (kbdbl_ctl->timeout << 0x10), &ignore);
1890 }
1891
1892 struct battery_care_control {
1893         struct device_attribute attrs[2];
1894         unsigned int handle;
1895 };
1896 static struct battery_care_control *bcare_ctl;
1897
1898 static ssize_t sony_nc_battery_care_limit_store(struct device *dev,
1899                 struct device_attribute *attr,
1900                 const char *buffer, size_t count)
1901 {
1902         unsigned int result, cmd;
1903         unsigned long value;
1904
1905         if (count > 31)
1906                 return -EINVAL;
1907
1908         if (kstrtoul(buffer, 10, &value))
1909                 return -EINVAL;
1910
1911         /*  limit values (2 bits):
1912          *  00 - none
1913          *  01 - 80%
1914          *  10 - 50%
1915          *  11 - 100%
1916          *
1917          *  bit 0: 0 disable BCL, 1 enable BCL
1918          *  bit 1: 1 tell to store the battery limit (see bits 6,7) too
1919          *  bits 2,3: reserved
1920          *  bits 4,5: store the limit into the EC
1921          *  bits 6,7: store the limit into the battery
1922          */
1923         cmd = 0;
1924
1925         if (value > 0) {
1926                 if (value <= 50)
1927                         cmd = 0x20;
1928
1929                 else if (value <= 80)
1930                         cmd = 0x10;
1931
1932                 else if (value <= 100)
1933                         cmd = 0x30;
1934
1935                 else
1936                         return -EINVAL;
1937
1938                 /*
1939                  * handle 0x0115 should allow storing on battery too;
1940                  * handle 0x0136 same as 0x0115 + health status;
1941                  * handle 0x013f, same as 0x0136 but no storing on the battery
1942                  */
1943                 if (bcare_ctl->handle != 0x013f)
1944                         cmd = cmd | (cmd << 2);
1945
1946                 cmd = (cmd | 0x1) << 0x10;
1947         }
1948
1949         if (sony_call_snc_handle(bcare_ctl->handle, cmd | 0x0100, &result))
1950                 return -EIO;
1951
1952         return count;
1953 }
1954
1955 static ssize_t sony_nc_battery_care_limit_show(struct device *dev,
1956                 struct device_attribute *attr, char *buffer)
1957 {
1958         unsigned int result, status;
1959
1960         if (sony_call_snc_handle(bcare_ctl->handle, 0x0000, &result))
1961                 return -EIO;
1962
1963         status = (result & 0x01) ? ((result & 0x30) >> 0x04) : 0;
1964         switch (status) {
1965         case 1:
1966                 status = 80;
1967                 break;
1968         case 2:
1969                 status = 50;
1970                 break;
1971         case 3:
1972                 status = 100;
1973                 break;
1974         default:
1975                 status = 0;
1976                 break;
1977         }
1978
1979         return snprintf(buffer, PAGE_SIZE, "%d\n", status);
1980 }
1981
1982 static ssize_t sony_nc_battery_care_health_show(struct device *dev,
1983                 struct device_attribute *attr, char *buffer)
1984 {
1985         ssize_t count = 0;
1986         unsigned int health;
1987
1988         if (sony_call_snc_handle(bcare_ctl->handle, 0x0200, &health))
1989                 return -EIO;
1990
1991         count = snprintf(buffer, PAGE_SIZE, "%d\n", health & 0xff);
1992
1993         return count;
1994 }
1995
1996 static int sony_nc_battery_care_setup(struct platform_device *pd,
1997                 unsigned int handle)
1998 {
1999         int ret = 0;
2000
2001         bcare_ctl = kzalloc(sizeof(struct battery_care_control), GFP_KERNEL);
2002         if (!bcare_ctl)
2003                 return -ENOMEM;
2004
2005         bcare_ctl->handle = handle;
2006
2007         sysfs_attr_init(&bcare_ctl->attrs[0].attr);
2008         bcare_ctl->attrs[0].attr.name = "battery_care_limiter";
2009         bcare_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR;
2010         bcare_ctl->attrs[0].show = sony_nc_battery_care_limit_show;
2011         bcare_ctl->attrs[0].store = sony_nc_battery_care_limit_store;
2012
2013         ret = device_create_file(&pd->dev, &bcare_ctl->attrs[0]);
2014         if (ret)
2015                 goto outkzalloc;
2016
2017         /* 0x0115 is for models with no health reporting capability */
2018         if (handle == 0x0115)
2019                 return 0;
2020
2021         sysfs_attr_init(&bcare_ctl->attrs[1].attr);
2022         bcare_ctl->attrs[1].attr.name = "battery_care_health";
2023         bcare_ctl->attrs[1].attr.mode = S_IRUGO;
2024         bcare_ctl->attrs[1].show = sony_nc_battery_care_health_show;
2025
2026         ret = device_create_file(&pd->dev, &bcare_ctl->attrs[1]);
2027         if (ret)
2028                 goto outlimiter;
2029
2030         return 0;
2031
2032 outlimiter:
2033         device_remove_file(&pd->dev, &bcare_ctl->attrs[0]);
2034
2035 outkzalloc:
2036         kfree(bcare_ctl);
2037         bcare_ctl = NULL;
2038
2039         return ret;
2040 }
2041
2042 static void sony_nc_battery_care_cleanup(struct platform_device *pd)
2043 {
2044         if (bcare_ctl) {
2045                 device_remove_file(&pd->dev, &bcare_ctl->attrs[0]);
2046                 if (bcare_ctl->handle != 0x0115)
2047                         device_remove_file(&pd->dev, &bcare_ctl->attrs[1]);
2048
2049                 kfree(bcare_ctl);
2050                 bcare_ctl = NULL;
2051         }
2052 }
2053
2054 struct snc_thermal_ctrl {
2055         unsigned int mode;
2056         unsigned int profiles;
2057         struct device_attribute mode_attr;
2058         struct device_attribute profiles_attr;
2059 };
2060 static struct snc_thermal_ctrl *th_handle;
2061
2062 #define THM_PROFILE_MAX 3
2063 static const char * const snc_thermal_profiles[] = {
2064         "balanced",
2065         "silent",
2066         "performance"
2067 };
2068
2069 static int sony_nc_thermal_mode_set(unsigned short mode)
2070 {
2071         unsigned int result;
2072
2073         /* the thermal profile seems to be a two bit bitmask:
2074          * lsb -> silent
2075          * msb -> performance
2076          * no bit set is the normal operation and is always valid
2077          * Some vaio models only have "balanced" and "performance"
2078          */
2079         if ((mode && !(th_handle->profiles & mode)) || mode >= THM_PROFILE_MAX)
2080                 return -EINVAL;
2081
2082         if (sony_call_snc_handle(0x0122, mode << 0x10 | 0x0200, &result))
2083                 return -EIO;
2084
2085         th_handle->mode = mode;
2086
2087         return 0;
2088 }
2089
2090 static int sony_nc_thermal_mode_get(void)
2091 {
2092         unsigned int result;
2093
2094         if (sony_call_snc_handle(0x0122, 0x0100, &result))
2095                 return -EIO;
2096
2097         return result & 0xff;
2098 }
2099
2100 static ssize_t sony_nc_thermal_profiles_show(struct device *dev,
2101                 struct device_attribute *attr, char *buffer)
2102 {
2103         short cnt;
2104         size_t idx = 0;
2105
2106         for (cnt = 0; cnt < THM_PROFILE_MAX; cnt++) {
2107                 if (!cnt || (th_handle->profiles & cnt))
2108                         idx += snprintf(buffer + idx, PAGE_SIZE - idx, "%s ",
2109                                         snc_thermal_profiles[cnt]);
2110         }
2111         idx += snprintf(buffer + idx, PAGE_SIZE - idx, "\n");
2112
2113         return idx;
2114 }
2115
2116 static ssize_t sony_nc_thermal_mode_store(struct device *dev,
2117                 struct device_attribute *attr,
2118                 const char *buffer, size_t count)
2119 {
2120         unsigned short cmd;
2121         size_t len = count;
2122
2123         if (count == 0)
2124                 return -EINVAL;
2125
2126         /* skip the newline if present */
2127         if (buffer[len - 1] == '\n')
2128                 len--;
2129
2130         for (cmd = 0; cmd < THM_PROFILE_MAX; cmd++)
2131                 if (strncmp(buffer, snc_thermal_profiles[cmd], len) == 0)
2132                         break;
2133
2134         if (sony_nc_thermal_mode_set(cmd))
2135                 return -EIO;
2136
2137         return count;
2138 }
2139
2140 static ssize_t sony_nc_thermal_mode_show(struct device *dev,
2141                 struct device_attribute *attr, char *buffer)
2142 {
2143         ssize_t count = 0;
2144         int mode = sony_nc_thermal_mode_get();
2145
2146         if (mode < 0)
2147                 return mode;
2148
2149         count = snprintf(buffer, PAGE_SIZE, "%s\n", snc_thermal_profiles[mode]);
2150
2151         return count;
2152 }
2153
2154 static int sony_nc_thermal_setup(struct platform_device *pd)
2155 {
2156         int ret = 0;
2157         th_handle = kzalloc(sizeof(struct snc_thermal_ctrl), GFP_KERNEL);
2158         if (!th_handle)
2159                 return -ENOMEM;
2160
2161         ret = sony_call_snc_handle(0x0122, 0x0000, &th_handle->profiles);
2162         if (ret) {
2163                 pr_warn("couldn't to read the thermal profiles\n");
2164                 goto outkzalloc;
2165         }
2166
2167         ret = sony_nc_thermal_mode_get();
2168         if (ret < 0) {
2169                 pr_warn("couldn't to read the current thermal profile");
2170                 goto outkzalloc;
2171         }
2172         th_handle->mode = ret;
2173
2174         sysfs_attr_init(&th_handle->profiles_attr.attr);
2175         th_handle->profiles_attr.attr.name = "thermal_profiles";
2176         th_handle->profiles_attr.attr.mode = S_IRUGO;
2177         th_handle->profiles_attr.show = sony_nc_thermal_profiles_show;
2178
2179         sysfs_attr_init(&th_handle->mode_attr.attr);
2180         th_handle->mode_attr.attr.name = "thermal_control";
2181         th_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
2182         th_handle->mode_attr.show = sony_nc_thermal_mode_show;
2183         th_handle->mode_attr.store = sony_nc_thermal_mode_store;
2184
2185         ret = device_create_file(&pd->dev, &th_handle->profiles_attr);
2186         if (ret)
2187                 goto outkzalloc;
2188
2189         ret = device_create_file(&pd->dev, &th_handle->mode_attr);
2190         if (ret)
2191                 goto outprofiles;
2192
2193         return 0;
2194
2195 outprofiles:
2196         device_remove_file(&pd->dev, &th_handle->profiles_attr);
2197 outkzalloc:
2198         kfree(th_handle);
2199         th_handle = NULL;
2200         return ret;
2201 }
2202
2203 static void sony_nc_thermal_cleanup(struct platform_device *pd)
2204 {
2205         if (th_handle) {
2206                 device_remove_file(&pd->dev, &th_handle->profiles_attr);
2207                 device_remove_file(&pd->dev, &th_handle->mode_attr);
2208                 kfree(th_handle);
2209                 th_handle = NULL;
2210         }
2211 }
2212
2213 static void sony_nc_thermal_resume(void)
2214 {
2215         unsigned int status = sony_nc_thermal_mode_get();
2216
2217         if (status != th_handle->mode)
2218                 sony_nc_thermal_mode_set(th_handle->mode);
2219 }
2220
2221 /* resume on LID open */
2222 struct snc_lid_resume_control {
2223         struct device_attribute attrs[3];
2224         unsigned int status;
2225 };
2226 static struct snc_lid_resume_control *lid_ctl;
2227
2228 static ssize_t sony_nc_lid_resume_store(struct device *dev,
2229                                         struct device_attribute *attr,
2230                                         const char *buffer, size_t count)
2231 {
2232         unsigned int result, pos;
2233         unsigned long value;
2234         if (count > 31)
2235                 return -EINVAL;
2236
2237         if (kstrtoul(buffer, 10, &value) || value > 1)
2238                 return -EINVAL;
2239
2240         /* the value we have to write to SNC is a bitmask:
2241          * +--------------+
2242          * | S3 | S4 | S5 |
2243          * +--------------+
2244          *   2    1    0
2245          */
2246         if (strcmp(attr->attr.name, "lid_resume_S3") == 0)
2247                 pos = 2;
2248         else if (strcmp(attr->attr.name, "lid_resume_S4") == 0)
2249                 pos = 1;
2250         else if (strcmp(attr->attr.name, "lid_resume_S5") == 0)
2251                 pos = 0;
2252         else
2253                return -EINVAL;
2254
2255         if (value)
2256                 value = lid_ctl->status | (1 << pos);
2257         else
2258                 value = lid_ctl->status & ~(1 << pos);
2259
2260         if (sony_call_snc_handle(0x0119, value << 0x10 | 0x0100, &result))
2261                 return -EIO;
2262
2263         lid_ctl->status = value;
2264
2265         return count;
2266 }
2267
2268 static ssize_t sony_nc_lid_resume_show(struct device *dev,
2269                                        struct device_attribute *attr, char *buffer)
2270 {
2271         unsigned int pos;
2272
2273         if (strcmp(attr->attr.name, "lid_resume_S3") == 0)
2274                 pos = 2;
2275         else if (strcmp(attr->attr.name, "lid_resume_S4") == 0)
2276                 pos = 1;
2277         else if (strcmp(attr->attr.name, "lid_resume_S5") == 0)
2278                 pos = 0;
2279         else
2280                 return -EINVAL;
2281                
2282         return snprintf(buffer, PAGE_SIZE, "%d\n",
2283                         (lid_ctl->status >> pos) & 0x01);
2284 }
2285
2286 static int sony_nc_lid_resume_setup(struct platform_device *pd)
2287 {
2288         unsigned int result;
2289         int i;
2290
2291         if (sony_call_snc_handle(0x0119, 0x0000, &result))
2292                 return -EIO;
2293
2294         lid_ctl = kzalloc(sizeof(struct snc_lid_resume_control), GFP_KERNEL);
2295         if (!lid_ctl)
2296                 return -ENOMEM;
2297
2298         lid_ctl->status = result & 0x7;
2299
2300         sysfs_attr_init(&lid_ctl->attrs[0].attr);
2301         lid_ctl->attrs[0].attr.name = "lid_resume_S3";
2302         lid_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR;
2303         lid_ctl->attrs[0].show = sony_nc_lid_resume_show;
2304         lid_ctl->attrs[0].store = sony_nc_lid_resume_store;
2305
2306         sysfs_attr_init(&lid_ctl->attrs[1].attr);
2307         lid_ctl->attrs[1].attr.name = "lid_resume_S4";
2308         lid_ctl->attrs[1].attr.mode = S_IRUGO | S_IWUSR;
2309         lid_ctl->attrs[1].show = sony_nc_lid_resume_show;
2310         lid_ctl->attrs[1].store = sony_nc_lid_resume_store;
2311
2312         sysfs_attr_init(&lid_ctl->attrs[2].attr);
2313         lid_ctl->attrs[2].attr.name = "lid_resume_S5";
2314         lid_ctl->attrs[2].attr.mode = S_IRUGO | S_IWUSR;
2315         lid_ctl->attrs[2].show = sony_nc_lid_resume_show;
2316         lid_ctl->attrs[2].store = sony_nc_lid_resume_store;
2317
2318         for (i = 0; i < 3; i++) {
2319                 result = device_create_file(&pd->dev, &lid_ctl->attrs[i]);
2320                 if (result)
2321                         goto liderror;
2322         }
2323
2324         return 0;
2325
2326 liderror:
2327         for (; i > 0; i--)
2328                 device_remove_file(&pd->dev, &lid_ctl->attrs[i]);
2329
2330         kfree(lid_ctl);
2331         lid_ctl = NULL;
2332
2333         return result;
2334 }
2335
2336 static void sony_nc_lid_resume_cleanup(struct platform_device *pd)
2337 {
2338         int i;
2339
2340         if (lid_ctl) {
2341                 for (i = 0; i < 3; i++)
2342                         device_remove_file(&pd->dev, &lid_ctl->attrs[i]);
2343
2344                 kfree(lid_ctl);
2345                 lid_ctl = NULL;
2346         }
2347 }
2348
2349 /* High speed charging function */
2350 static struct device_attribute *hsc_handle;
2351
2352 static ssize_t sony_nc_highspeed_charging_store(struct device *dev,
2353                 struct device_attribute *attr,
2354                 const char *buffer, size_t count)
2355 {
2356         unsigned int result;
2357         unsigned long value;
2358
2359         if (count > 31)
2360                 return -EINVAL;
2361
2362         if (kstrtoul(buffer, 10, &value) || value > 1)
2363                 return -EINVAL;
2364
2365         if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result))
2366                 return -EIO;
2367
2368         return count;
2369 }
2370
2371 static ssize_t sony_nc_highspeed_charging_show(struct device *dev,
2372                 struct device_attribute *attr, char *buffer)
2373 {
2374         unsigned int result;
2375
2376         if (sony_call_snc_handle(0x0131, 0x0100, &result))
2377                 return -EIO;
2378
2379         return snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01);
2380 }
2381
2382 static int sony_nc_highspeed_charging_setup(struct platform_device *pd)
2383 {
2384         unsigned int result;
2385
2386         if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) {
2387                 /* some models advertise the handle but have no implementation
2388                  * for it
2389                  */
2390                 pr_info("No High Speed Charging capability found\n");
2391                 return 0;
2392         }
2393
2394         hsc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2395         if (!hsc_handle)
2396                 return -ENOMEM;
2397
2398         sysfs_attr_init(&hsc_handle->attr);
2399         hsc_handle->attr.name = "battery_highspeed_charging";
2400         hsc_handle->attr.mode = S_IRUGO | S_IWUSR;
2401         hsc_handle->show = sony_nc_highspeed_charging_show;
2402         hsc_handle->store = sony_nc_highspeed_charging_store;
2403
2404         result = device_create_file(&pd->dev, hsc_handle);
2405         if (result) {
2406                 kfree(hsc_handle);
2407                 hsc_handle = NULL;
2408                 return result;
2409         }
2410
2411         return 0;
2412 }
2413
2414 static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd)
2415 {
2416         if (hsc_handle) {
2417                 device_remove_file(&pd->dev, hsc_handle);
2418                 kfree(hsc_handle);
2419                 hsc_handle = NULL;
2420         }
2421 }
2422
2423 /* Touchpad enable/disable */
2424 struct touchpad_control {
2425         struct device_attribute attr;
2426         int handle;
2427 };
2428 static struct touchpad_control *tp_ctl;
2429
2430 static ssize_t sony_nc_touchpad_store(struct device *dev,
2431                 struct device_attribute *attr, const char *buffer, size_t count)
2432 {
2433         unsigned int result;
2434         unsigned long value;
2435
2436         if (count > 31)
2437                 return -EINVAL;
2438
2439         if (kstrtoul(buffer, 10, &value) || value > 1)
2440                 return -EINVAL;
2441
2442         /* sysfs: 0 disabled, 1 enabled
2443          * EC: 0 enabled, 1 disabled
2444          */
2445         if (sony_call_snc_handle(tp_ctl->handle,
2446                                 (!value << 0x10) | 0x100, &result))
2447                 return -EIO;
2448
2449         return count;
2450 }
2451
2452 static ssize_t sony_nc_touchpad_show(struct device *dev,
2453                 struct device_attribute *attr, char *buffer)
2454 {
2455         unsigned int result;
2456
2457         if (sony_call_snc_handle(tp_ctl->handle, 0x000, &result))
2458                 return -EINVAL;
2459
2460         return snprintf(buffer, PAGE_SIZE, "%d\n", !(result & 0x01));
2461 }
2462
2463 static int sony_nc_touchpad_setup(struct platform_device *pd,
2464                 unsigned int handle)
2465 {
2466         int ret = 0;
2467
2468         tp_ctl = kzalloc(sizeof(struct touchpad_control), GFP_KERNEL);
2469         if (!tp_ctl)
2470                 return -ENOMEM;
2471
2472         tp_ctl->handle = handle;
2473
2474         sysfs_attr_init(&tp_ctl->attr.attr);
2475         tp_ctl->attr.attr.name = "touchpad";
2476         tp_ctl->attr.attr.mode = S_IRUGO | S_IWUSR;
2477         tp_ctl->attr.show = sony_nc_touchpad_show;
2478         tp_ctl->attr.store = sony_nc_touchpad_store;
2479
2480         ret = device_create_file(&pd->dev, &tp_ctl->attr);
2481         if (ret) {
2482                 kfree(tp_ctl);
2483                 tp_ctl = NULL;
2484         }
2485
2486         return ret;
2487 }
2488
2489 static void sony_nc_touchpad_cleanup(struct platform_device *pd)
2490 {
2491         if (tp_ctl) {
2492                 device_remove_file(&pd->dev, &tp_ctl->attr);
2493                 kfree(tp_ctl);
2494                 tp_ctl = NULL;
2495         }
2496 }
2497
2498 static void sony_nc_backlight_ng_read_limits(int handle,
2499                 struct sony_backlight_props *props)
2500 {
2501         u64 offset;
2502         int i;
2503         int lvl_table_len = 0;
2504         u8 min = 0xff, max = 0x00;
2505         unsigned char buffer[32] = { 0 };
2506
2507         props->handle = handle;
2508         props->offset = 0;
2509         props->maxlvl = 0xff;
2510
2511         offset = sony_find_snc_handle(handle);
2512
2513         /* try to read the boundaries from ACPI tables, if we fail the above
2514          * defaults should be reasonable
2515          */
2516         i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer,
2517                         32);
2518         if (i < 0)
2519                 return;
2520
2521         switch (handle) {
2522         case 0x012f:
2523         case 0x0137:
2524                 lvl_table_len = 9;
2525                 break;
2526         case 0x143:
2527                 lvl_table_len = 16;
2528                 break;
2529         }
2530
2531         /* the buffer lists brightness levels available, brightness levels are
2532          * from position 0 to 8 in the array, other values are used by ALS
2533          * control.
2534          */
2535         for (i = 0; i < lvl_table_len && i < ARRAY_SIZE(buffer); i++) {
2536
2537                 dprintk("Brightness level: %d\n", buffer[i]);
2538
2539                 if (!buffer[i])
2540                         break;
2541
2542                 if (buffer[i] > max)
2543                         max = buffer[i];
2544                 if (buffer[i] < min)
2545                         min = buffer[i];
2546         }
2547         props->offset = min;
2548         props->maxlvl = max;
2549         dprintk("Brightness levels: min=%d max=%d\n", props->offset,
2550                         props->maxlvl);
2551 }
2552
2553 static void sony_nc_backlight_setup(void)
2554 {
2555         acpi_handle unused;
2556         int max_brightness = 0;
2557         const struct backlight_ops *ops = NULL;
2558         struct backlight_properties props;
2559
2560         if (sony_find_snc_handle(0x12f) >= 0) {
2561                 ops = &sony_backlight_ng_ops;
2562                 sony_bl_props.cmd_base = 0x0100;
2563                 sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
2564                 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
2565
2566         } else if (sony_find_snc_handle(0x137) >= 0) {
2567                 ops = &sony_backlight_ng_ops;
2568                 sony_bl_props.cmd_base = 0x0100;
2569                 sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
2570                 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
2571
2572         } else if (sony_find_snc_handle(0x143) >= 0) {
2573                 ops = &sony_backlight_ng_ops;
2574                 sony_bl_props.cmd_base = 0x3000;
2575                 sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props);
2576                 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
2577
2578         } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
2579                                                 &unused))) {
2580                 ops = &sony_backlight_ops;
2581                 max_brightness = SONY_MAX_BRIGHTNESS - 1;
2582
2583         } else
2584                 return;
2585
2586         memset(&props, 0, sizeof(struct backlight_properties));
2587         props.type = BACKLIGHT_PLATFORM;
2588         props.max_brightness = max_brightness;
2589         sony_bl_props.dev = backlight_device_register("sony", NULL,
2590                                                       &sony_bl_props,
2591                                                       ops, &props);
2592
2593         if (IS_ERR(sony_bl_props.dev)) {
2594                 pr_warn("unable to register backlight device\n");
2595                 sony_bl_props.dev = NULL;
2596         } else
2597                 sony_bl_props.dev->props.brightness =
2598                         ops->get_brightness(sony_bl_props.dev);
2599 }
2600
2601 static void sony_nc_backlight_cleanup(void)
2602 {
2603         if (sony_bl_props.dev)
2604                 backlight_device_unregister(sony_bl_props.dev);
2605 }
2606
2607 static int sony_nc_add(struct acpi_device *device)
2608 {
2609         acpi_status status;
2610         int result = 0;
2611         acpi_handle handle;
2612         struct sony_nc_value *item;
2613
2614         pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
2615
2616         sony_nc_acpi_device = device;
2617         strcpy(acpi_device_class(device), "sony/hotkey");
2618
2619         sony_nc_acpi_handle = device->handle;
2620
2621         /* read device status */
2622         result = acpi_bus_get_status(device);
2623         /* bail IFF the above call was successful and the device is not present */
2624         if (!result && !device->status.present) {
2625                 dprintk("Device not present\n");
2626                 result = -ENODEV;
2627                 goto outwalk;
2628         }
2629
2630         result = sony_pf_add();
2631         if (result)
2632                 goto outpresent;
2633
2634         if (debug) {
2635                 status = acpi_walk_namespace(ACPI_TYPE_METHOD,
2636                                 sony_nc_acpi_handle, 1, sony_walk_callback,
2637                                 NULL, NULL, NULL);
2638                 if (ACPI_FAILURE(status)) {
2639                         pr_warn("unable to walk acpi resources\n");
2640                         result = -ENODEV;
2641                         goto outpresent;
2642                 }
2643         }
2644
2645         result = sony_laptop_setup_input(device);
2646         if (result) {
2647                 pr_err("Unable to create input devices\n");
2648                 goto outplatform;
2649         }
2650
2651         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
2652                                          &handle))) {
2653                 int arg = 1;
2654                 if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
2655                         dprintk("ECON Method failed\n");
2656         }
2657
2658         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
2659                                          &handle))) {
2660                 dprintk("Doing SNC setup\n");
2661                 /* retrieve the available handles */
2662                 result = sony_nc_handles_setup(sony_pf_device);
2663                 if (!result)
2664                         sony_nc_function_setup(device, sony_pf_device);
2665         }
2666
2667         /* setup input devices and helper fifo */
2668         if (acpi_video_backlight_support()) {
2669                 pr_info("brightness ignored, must be controlled by ACPI video driver\n");
2670         } else {
2671                 sony_nc_backlight_setup();
2672         }
2673
2674         /* create sony_pf sysfs attributes related to the SNC device */
2675         for (item = sony_nc_values; item->name; ++item) {
2676
2677                 if (!debug && item->debug)
2678                         continue;
2679
2680                 /* find the available acpiget as described in the DSDT */
2681                 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
2682                         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
2683                                                          *item->acpiget,
2684                                                          &handle))) {
2685                                 dprintk("Found %s getter: %s\n",
2686                                                 item->name, *item->acpiget);
2687                                 item->devattr.attr.mode |= S_IRUGO;
2688                                 break;
2689                         }
2690                 }
2691
2692                 /* find the available acpiset as described in the DSDT */
2693                 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
2694                         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
2695                                                          *item->acpiset,
2696                                                          &handle))) {
2697                                 dprintk("Found %s setter: %s\n",
2698                                                 item->name, *item->acpiset);
2699                                 item->devattr.attr.mode |= S_IWUSR;
2700                                 break;
2701                         }
2702                 }
2703
2704                 if (item->devattr.attr.mode != 0) {
2705                         result =
2706                             device_create_file(&sony_pf_device->dev,
2707                                                &item->devattr);
2708                         if (result)
2709                                 goto out_sysfs;
2710                 }
2711         }
2712
2713         return 0;
2714
2715 out_sysfs:
2716         for (item = sony_nc_values; item->name; ++item) {
2717                 device_remove_file(&sony_pf_device->dev, &item->devattr);
2718         }
2719         sony_nc_backlight_cleanup();
2720         sony_nc_function_cleanup(sony_pf_device);
2721         sony_nc_handles_cleanup(sony_pf_device);
2722
2723 outplatform:
2724         sony_laptop_remove_input();
2725
2726 outpresent:
2727         sony_pf_remove();
2728
2729 outwalk:
2730         sony_nc_rfkill_cleanup();
2731         return result;
2732 }
2733
2734 static int sony_nc_remove(struct acpi_device *device, int type)
2735 {
2736         struct sony_nc_value *item;
2737
2738         sony_nc_backlight_cleanup();
2739
2740         sony_nc_acpi_device = NULL;
2741
2742         for (item = sony_nc_values; item->name; ++item) {
2743                 device_remove_file(&sony_pf_device->dev, &item->devattr);
2744         }
2745
2746         sony_nc_function_cleanup(sony_pf_device);
2747         sony_nc_handles_cleanup(sony_pf_device);
2748         sony_pf_remove();
2749         sony_laptop_remove_input();
2750         dprintk(SONY_NC_DRIVER_NAME " removed.\n");
2751
2752         return 0;
2753 }
2754
2755 static const struct acpi_device_id sony_device_ids[] = {
2756         {SONY_NC_HID, 0},
2757         {SONY_PIC_HID, 0},
2758         {"", 0},
2759 };
2760 MODULE_DEVICE_TABLE(acpi, sony_device_ids);
2761
2762 static const struct acpi_device_id sony_nc_device_ids[] = {
2763         {SONY_NC_HID, 0},
2764         {"", 0},
2765 };
2766
2767 static struct acpi_driver sony_nc_driver = {
2768         .name = SONY_NC_DRIVER_NAME,
2769         .class = SONY_NC_CLASS,
2770         .ids = sony_nc_device_ids,
2771         .owner = THIS_MODULE,
2772         .ops = {
2773                 .add = sony_nc_add,
2774                 .remove = sony_nc_remove,
2775                 .notify = sony_nc_notify,
2776                 },
2777         .drv.pm = &sony_nc_pm,
2778 };
2779
2780 /*********** SPIC (SNY6001) Device ***********/
2781
2782 #define SONYPI_DEVICE_TYPE1     0x00000001
2783 #define SONYPI_DEVICE_TYPE2     0x00000002
2784 #define SONYPI_DEVICE_TYPE3     0x00000004
2785
2786 #define SONYPI_TYPE1_OFFSET     0x04
2787 #define SONYPI_TYPE2_OFFSET     0x12
2788 #define SONYPI_TYPE3_OFFSET     0x12
2789
2790 struct sony_pic_ioport {
2791         struct acpi_resource_io io1;
2792         struct acpi_resource_io io2;
2793         struct list_head        list;
2794 };
2795
2796 struct sony_pic_irq {
2797         struct acpi_resource_irq        irq;
2798         struct list_head                list;
2799 };
2800
2801 struct sonypi_eventtypes {
2802         u8                      data;
2803         unsigned long           mask;
2804         struct sonypi_event     *events;
2805 };
2806
2807 struct sony_pic_dev {
2808         struct acpi_device              *acpi_dev;
2809         struct sony_pic_irq             *cur_irq;
2810         struct sony_pic_ioport          *cur_ioport;
2811         struct list_head                interrupts;
2812         struct list_head                ioports;
2813         struct mutex                    lock;
2814         struct sonypi_eventtypes        *event_types;
2815         int                             (*handle_irq)(const u8, const u8);
2816         int                             model;
2817         u16                             evport_offset;
2818         u8                              camera_power;
2819         u8                              bluetooth_power;
2820         u8                              wwan_power;
2821 };
2822
2823 static struct sony_pic_dev spic_dev = {
2824         .interrupts     = LIST_HEAD_INIT(spic_dev.interrupts),
2825         .ioports        = LIST_HEAD_INIT(spic_dev.ioports),
2826 };
2827
2828 static int spic_drv_registered;
2829
2830 /* Event masks */
2831 #define SONYPI_JOGGER_MASK                      0x00000001
2832 #define SONYPI_CAPTURE_MASK                     0x00000002
2833 #define SONYPI_FNKEY_MASK                       0x00000004
2834 #define SONYPI_BLUETOOTH_MASK                   0x00000008
2835 #define SONYPI_PKEY_MASK                        0x00000010
2836 #define SONYPI_BACK_MASK                        0x00000020
2837 #define SONYPI_HELP_MASK                        0x00000040
2838 #define SONYPI_LID_MASK                         0x00000080
2839 #define SONYPI_ZOOM_MASK                        0x00000100
2840 #define SONYPI_THUMBPHRASE_MASK                 0x00000200
2841 #define SONYPI_MEYE_MASK                        0x00000400
2842 #define SONYPI_MEMORYSTICK_MASK                 0x00000800
2843 #define SONYPI_BATTERY_MASK                     0x00001000
2844 #define SONYPI_WIRELESS_MASK                    0x00002000
2845
2846 struct sonypi_event {
2847         u8      data;
2848         u8      event;
2849 };
2850
2851 /* The set of possible button release events */
2852 static struct sonypi_event sonypi_releaseev[] = {
2853         { 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED },
2854         { 0, 0 }
2855 };
2856
2857 /* The set of possible jogger events  */
2858 static struct sonypi_event sonypi_joggerev[] = {
2859         { 0x1f, SONYPI_EVENT_JOGDIAL_UP },
2860         { 0x01, SONYPI_EVENT_JOGDIAL_DOWN },
2861         { 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED },
2862         { 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED },
2863         { 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP },
2864         { 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN },
2865         { 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED },
2866         { 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED },
2867         { 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP },
2868         { 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN },
2869         { 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED },
2870         { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED },
2871         { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED },
2872         { 0, 0 }
2873 };
2874
2875 /* The set of possible capture button events */
2876 static struct sonypi_event sonypi_captureev[] = {
2877         { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
2878         { 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
2879         { 0x40, SONYPI_EVENT_CAPTURE_PRESSED },
2880         { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
2881         { 0, 0 }
2882 };
2883
2884 /* The set of possible fnkeys events */
2885 static struct sonypi_event sonypi_fnkeyev[] = {
2886         { 0x10, SONYPI_EVENT_FNKEY_ESC },
2887         { 0x11, SONYPI_EVENT_FNKEY_F1 },
2888         { 0x12, SONYPI_EVENT_FNKEY_F2 },
2889         { 0x13, SONYPI_EVENT_FNKEY_F3 },
2890         { 0x14, SONYPI_EVENT_FNKEY_F4 },
2891         { 0x15, SONYPI_EVENT_FNKEY_F5 },
2892         { 0x16, SONYPI_EVENT_FNKEY_F6 },
2893         { 0x17, SONYPI_EVENT_FNKEY_F7 },
2894         { 0x18, SONYPI_EVENT_FNKEY_F8 },
2895         { 0x19, SONYPI_EVENT_FNKEY_F9 },
2896         { 0x1a, SONYPI_EVENT_FNKEY_F10 },
2897         { 0x1b, SONYPI_EVENT_FNKEY_F11 },
2898         { 0x1c, SONYPI_EVENT_FNKEY_F12 },
2899         { 0x1f, SONYPI_EVENT_FNKEY_RELEASED },
2900         { 0x21, SONYPI_EVENT_FNKEY_1 },
2901         { 0x22, SONYPI_EVENT_FNKEY_2 },
2902         { 0x31, SONYPI_EVENT_FNKEY_D },
2903         { 0x32, SONYPI_EVENT_FNKEY_E },
2904         { 0x33, SONYPI_EVENT_FNKEY_F },
2905         { 0x34, SONYPI_EVENT_FNKEY_S },
2906         { 0x35, SONYPI_EVENT_FNKEY_B },
2907         { 0x36, SONYPI_EVENT_FNKEY_ONLY },
2908         { 0, 0 }
2909 };
2910
2911 /* The set of possible program key events */
2912 static struct sonypi_event sonypi_pkeyev[] = {
2913         { 0x01, SONYPI_EVENT_PKEY_P1 },
2914         { 0x02, SONYPI_EVENT_PKEY_P2 },
2915         { 0x04, SONYPI_EVENT_PKEY_P3 },
2916         { 0x20, SONYPI_EVENT_PKEY_P1 },
2917         { 0, 0 }
2918 };
2919
2920 /* The set of possible bluetooth events */
2921 static struct sonypi_event sonypi_blueev[] = {
2922         { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
2923         { 0x59, SONYPI_EVENT_BLUETOOTH_ON },
2924         { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
2925         { 0, 0 }
2926 };
2927
2928 /* The set of possible wireless events */
2929 static struct sonypi_event sonypi_wlessev[] = {
2930         { 0x59, SONYPI_EVENT_IGNORE },
2931         { 0x5a, SONYPI_EVENT_IGNORE },
2932         { 0, 0 }
2933 };
2934
2935 /* The set of possible back button events */
2936 static struct sonypi_event sonypi_backev[] = {
2937         { 0x20, SONYPI_EVENT_BACK_PRESSED },
2938         { 0, 0 }
2939 };
2940
2941 /* The set of possible help button events */
2942 static struct sonypi_event sonypi_helpev[] = {
2943         { 0x3b, SONYPI_EVENT_HELP_PRESSED },
2944         { 0, 0 }
2945 };
2946
2947
2948 /* The set of possible lid events */
2949 static struct sonypi_event sonypi_lidev[] = {
2950         { 0x51, SONYPI_EVENT_LID_CLOSED },
2951         { 0x50, SONYPI_EVENT_LID_OPENED },
2952         { 0, 0 }
2953 };
2954
2955 /* The set of possible zoom events */
2956 static struct sonypi_event sonypi_zoomev[] = {
2957         { 0x39, SONYPI_EVENT_ZOOM_PRESSED },
2958         { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED },
2959         { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED },
2960         { 0x04, SONYPI_EVENT_ZOOM_PRESSED },
2961         { 0, 0 }
2962 };
2963
2964 /* The set of possible thumbphrase events */
2965 static struct sonypi_event sonypi_thumbphraseev[] = {
2966         { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED },
2967         { 0, 0 }
2968 };
2969
2970 /* The set of possible motioneye camera events */
2971 static struct sonypi_event sonypi_meyeev[] = {
2972         { 0x00, SONYPI_EVENT_MEYE_FACE },
2973         { 0x01, SONYPI_EVENT_MEYE_OPPOSITE },
2974         { 0, 0 }
2975 };
2976
2977 /* The set of possible memorystick events */
2978 static struct sonypi_event sonypi_memorystickev[] = {
2979         { 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT },
2980         { 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT },
2981         { 0, 0 }
2982 };
2983
2984 /* The set of possible battery events */
2985 static struct sonypi_event sonypi_batteryev[] = {
2986         { 0x20, SONYPI_EVENT_BATTERY_INSERT },
2987         { 0x30, SONYPI_EVENT_BATTERY_REMOVE },
2988         { 0, 0 }
2989 };
2990
2991 /* The set of possible volume events */
2992 static struct sonypi_event sonypi_volumeev[] = {
2993         { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED },
2994         { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED },
2995         { 0, 0 }
2996 };
2997
2998 /* The set of possible brightness events */
2999 static struct sonypi_event sonypi_brightnessev[] = {
3000         { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED },
3001         { 0, 0 }
3002 };
3003
3004 static struct sonypi_eventtypes type1_events[] = {
3005         { 0, 0xffffffff, sonypi_releaseev },
3006         { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
3007         { 0x30, SONYPI_LID_MASK, sonypi_lidev },
3008         { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
3009         { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
3010         { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3011         { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
3012         { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
3013         { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3014         { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
3015         { 0 },
3016 };
3017 static struct sonypi_eventtypes type2_events[] = {
3018         { 0, 0xffffffff, sonypi_releaseev },
3019         { 0x38, SONYPI_LID_MASK, sonypi_lidev },
3020         { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
3021         { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
3022         { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3023         { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
3024         { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
3025         { 0x11, SONYPI_BACK_MASK, sonypi_backev },
3026         { 0x21, SONYPI_HELP_MASK, sonypi_helpev },
3027         { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
3028         { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
3029         { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3030         { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
3031         { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
3032         { 0 },
3033 };
3034 static struct sonypi_eventtypes type3_events[] = {
3035         { 0, 0xffffffff, sonypi_releaseev },
3036         { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3037         { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
3038         { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3039         { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
3040         { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
3041         { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev },
3042         { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev },
3043         { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev },
3044         { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev },
3045         { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev },
3046         { 0 },
3047 };
3048
3049 /* low level spic calls */
3050 #define ITERATIONS_LONG         10000
3051 #define ITERATIONS_SHORT        10
3052 #define wait_on_command(command, iterations) {                          \
3053         unsigned int n = iterations;                                    \
3054         while (--n && (command))                                        \
3055                 udelay(1);                                              \
3056         if (!n)                                                         \
3057                 dprintk("command failed at %s : %s (line %d)\n",        \
3058                                 __FILE__, __func__, __LINE__);  \
3059 }
3060
3061 static u8 sony_pic_call1(u8 dev)
3062 {
3063         u8 v1, v2;
3064
3065         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3066                         ITERATIONS_LONG);
3067         outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3068         v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
3069         v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
3070         dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1);
3071         return v2;
3072 }
3073
3074 static u8 sony_pic_call2(u8 dev, u8 fn)
3075 {
3076         u8 v1;
3077
3078         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3079                         ITERATIONS_LONG);
3080         outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3081         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3082                         ITERATIONS_LONG);
3083         outb(fn, spic_dev.cur_ioport->io1.minimum);
3084         v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
3085         dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1);
3086         return v1;
3087 }
3088
3089 static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
3090 {
3091         u8 v1;
3092
3093         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3094         outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3095         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3096         outb(fn, spic_dev.cur_ioport->io1.minimum);
3097         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3098         outb(v, spic_dev.cur_ioport->io1.minimum);
3099         v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
3100         dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
3101                         dev, fn, v, v1);
3102         return v1;
3103 }
3104
3105 /*
3106  * minidrivers for SPIC models
3107  */
3108 static int type3_handle_irq(const u8 data_mask, const u8 ev)
3109 {
3110         /*
3111          * 0x31 could mean we have to take some extra action and wait for
3112          * the next irq for some Type3 models, it will generate a new
3113          * irq and we can read new data from the device:
3114          *  - 0x5c and 0x5f requires 0xA0
3115          *  - 0x61 requires 0xB3
3116          */
3117         if (data_mask == 0x31) {
3118                 if (ev == 0x5c || ev == 0x5f)
3119                         sony_pic_call1(0xA0);
3120                 else if (ev == 0x61)
3121                         sony_pic_call1(0xB3);
3122                 return 0;
3123         }
3124         return 1;
3125 }
3126
3127 static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
3128 {
3129         struct pci_dev *pcidev;
3130
3131         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3132                         PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
3133         if (pcidev) {
3134                 dev->model = SONYPI_DEVICE_TYPE1;
3135                 dev->evport_offset = SONYPI_TYPE1_OFFSET;
3136                 dev->event_types = type1_events;
3137                 goto out;
3138         }
3139
3140         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3141                         PCI_DEVICE_ID_INTEL_ICH6_1, NULL);
3142         if (pcidev) {
3143                 dev->model = SONYPI_DEVICE_TYPE2;
3144                 dev->evport_offset = SONYPI_TYPE2_OFFSET;
3145                 dev->event_types = type2_events;
3146                 goto out;
3147         }
3148
3149         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3150                         PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
3151         if (pcidev) {
3152                 dev->model = SONYPI_DEVICE_TYPE3;
3153                 dev->handle_irq = type3_handle_irq;
3154                 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3155                 dev->event_types = type3_events;
3156                 goto out;
3157         }
3158
3159         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3160                         PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
3161         if (pcidev) {
3162                 dev->model = SONYPI_DEVICE_TYPE3;
3163                 dev->handle_irq = type3_handle_irq;
3164                 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3165                 dev->event_types = type3_events;
3166                 goto out;
3167         }
3168
3169         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3170                         PCI_DEVICE_ID_INTEL_ICH9_1, NULL);
3171         if (pcidev) {
3172                 dev->model = SONYPI_DEVICE_TYPE3;
3173                 dev->handle_irq = type3_handle_irq;
3174                 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3175                 dev->event_types = type3_events;
3176                 goto out;
3177         }
3178
3179         /* default */
3180         dev->model = SONYPI_DEVICE_TYPE2;
3181         dev->evport_offset = SONYPI_TYPE2_OFFSET;
3182         dev->event_types = type2_events;
3183
3184 out:
3185         if (pcidev)
3186                 pci_dev_put(pcidev);
3187
3188         pr_info("detected Type%d model\n",
3189                 dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
3190                 dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
3191 }
3192
3193 /* camera tests and poweron/poweroff */
3194 #define SONYPI_CAMERA_PICTURE           5
3195 #define SONYPI_CAMERA_CONTROL           0x10
3196
3197 #define SONYPI_CAMERA_BRIGHTNESS                0
3198 #define SONYPI_CAMERA_CONTRAST                  1
3199 #define SONYPI_CAMERA_HUE                       2
3200 #define SONYPI_CAMERA_COLOR                     3
3201 #define SONYPI_CAMERA_SHARPNESS                 4
3202
3203 #define SONYPI_CAMERA_EXPOSURE_MASK             0xC
3204 #define SONYPI_CAMERA_WHITE_BALANCE_MASK        0x3
3205 #define SONYPI_CAMERA_PICTURE_MODE_MASK         0x30
3206 #define SONYPI_CAMERA_MUTE_MASK                 0x40
3207
3208 /* the rest don't need a loop until not 0xff */
3209 #define SONYPI_CAMERA_AGC                       6
3210 #define SONYPI_CAMERA_AGC_MASK                  0x30
3211 #define SONYPI_CAMERA_SHUTTER_MASK              0x7
3212
3213 #define SONYPI_CAMERA_SHUTDOWN_REQUEST          7
3214 #define SONYPI_CAMERA_CONTROL                   0x10
3215
3216 #define SONYPI_CAMERA_STATUS                    7
3217 #define SONYPI_CAMERA_STATUS_READY              0x2
3218 #define SONYPI_CAMERA_STATUS_POSITION           0x4
3219
3220 #define SONYPI_DIRECTION_BACKWARDS              0x4
3221
3222 #define SONYPI_CAMERA_REVISION                  8
3223 #define SONYPI_CAMERA_ROMVERSION                9
3224
3225 static int __sony_pic_camera_ready(void)
3226 {
3227         u8 v;
3228
3229         v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
3230         return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
3231 }
3232
3233 static int __sony_pic_camera_off(void)
3234 {
3235         if (!camera) {
3236                 pr_warn("camera control not enabled\n");
3237                 return -ENODEV;
3238         }
3239
3240         wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
3241                                 SONYPI_CAMERA_MUTE_MASK),
3242                         ITERATIONS_SHORT);
3243
3244         if (spic_dev.camera_power) {
3245                 sony_pic_call2(0x91, 0);
3246                 spic_dev.camera_power = 0;
3247         }
3248         return 0;
3249 }
3250
3251 static int __sony_pic_camera_on(void)
3252 {
3253         int i, j, x;
3254
3255         if (!camera) {
3256                 pr_warn("camera control not enabled\n");
3257                 return -ENODEV;
3258         }
3259
3260         if (spic_dev.camera_power)
3261                 return 0;
3262
3263         for (j = 5; j > 0; j--) {
3264
3265                 for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
3266                         msleep(10);
3267                 sony_pic_call1(0x93);
3268
3269                 for (i = 400; i > 0; i--) {
3270                         if (__sony_pic_camera_ready())
3271                                 break;
3272                         msleep(10);
3273                 }
3274                 if (i)
3275                         break;
3276         }
3277
3278         if (j == 0) {
3279                 pr_warn("failed to power on camera\n");
3280                 return -ENODEV;
3281         }
3282
3283         wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL,
3284                                 0x5a),
3285                         ITERATIONS_SHORT);
3286
3287         spic_dev.camera_power = 1;
3288         return 0;
3289 }
3290
3291 /* External camera command (exported to the motion eye v4l driver) */
3292 int sony_pic_camera_command(int command, u8 value)
3293 {
3294         if (!camera)
3295                 return -EIO;
3296
3297         mutex_lock(&spic_dev.lock);
3298
3299         switch (command) {
3300         case SONY_PIC_COMMAND_SETCAMERA:
3301                 if (value)
3302                         __sony_pic_camera_on();
3303                 else
3304                         __sony_pic_camera_off();
3305                 break;
3306         case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
3307                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value),
3308                                 ITERATIONS_SHORT);
3309                 break;
3310         case SONY_PIC_COMMAND_SETCAMERACONTRAST:
3311                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
3312                                 ITERATIONS_SHORT);
3313                 break;
3314         case SONY_PIC_COMMAND_SETCAMERAHUE:
3315                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
3316                                 ITERATIONS_SHORT);
3317                 break;
3318         case SONY_PIC_COMMAND_SETCAMERACOLOR:
3319                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
3320                                 ITERATIONS_SHORT);
3321                 break;
3322         case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
3323                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
3324                                 ITERATIONS_SHORT);
3325                 break;
3326         case SONY_PIC_COMMAND_SETCAMERAPICTURE:
3327                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
3328                                 ITERATIONS_SHORT);
3329                 break;
3330         case SONY_PIC_COMMAND_SETCAMERAAGC:
3331                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
3332                                 ITERATIONS_SHORT);
3333                 break;
3334         default:
3335                 pr_err("sony_pic_camera_command invalid: %d\n", command);
3336                 break;
3337         }
3338         mutex_unlock(&spic_dev.lock);
3339         return 0;
3340 }
3341 EXPORT_SYMBOL(sony_pic_camera_command);
3342
3343 /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */
3344 static void __sony_pic_set_wwanpower(u8 state)
3345 {
3346         state = !!state;
3347         if (spic_dev.wwan_power == state)
3348                 return;
3349         sony_pic_call2(0xB0, state);
3350         sony_pic_call1(0x82);
3351         spic_dev.wwan_power = state;
3352 }
3353
3354 static ssize_t sony_pic_wwanpower_store(struct device *dev,
3355                 struct device_attribute *attr,
3356                 const char *buffer, size_t count)
3357 {
3358         unsigned long value;
3359         if (count > 31)
3360                 return -EINVAL;
3361
3362         if (kstrtoul(buffer, 10, &value))
3363                 return -EINVAL;
3364
3365         mutex_lock(&spic_dev.lock);
3366         __sony_pic_set_wwanpower(value);
3367         mutex_unlock(&spic_dev.lock);
3368
3369         return count;
3370 }
3371
3372 static ssize_t sony_pic_wwanpower_show(struct device *dev,
3373                 struct device_attribute *attr, char *buffer)
3374 {
3375         ssize_t count;
3376         mutex_lock(&spic_dev.lock);
3377         count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.wwan_power);
3378         mutex_unlock(&spic_dev.lock);
3379         return count;
3380 }
3381
3382 /* bluetooth subsystem power state */
3383 static void __sony_pic_set_bluetoothpower(u8 state)
3384 {
3385         state = !!state;
3386         if (spic_dev.bluetooth_power == state)
3387                 return;
3388         sony_pic_call2(0x96, state);
3389         sony_pic_call1(0x82);
3390         spic_dev.bluetooth_power = state;
3391 }
3392
3393 static ssize_t sony_pic_bluetoothpower_store(struct device *dev,
3394                 struct device_attribute *attr,
3395                 const char *buffer, size_t count)
3396 {
3397         unsigned long value;
3398         if (count > 31)
3399                 return -EINVAL;
3400
3401         if (kstrtoul(buffer, 10, &value))
3402                 return -EINVAL;
3403
3404         mutex_lock(&spic_dev.lock);
3405         __sony_pic_set_bluetoothpower(value);
3406         mutex_unlock(&spic_dev.lock);
3407
3408         return count;
3409 }
3410
3411 static ssize_t sony_pic_bluetoothpower_show(struct device *dev,
3412                 struct device_attribute *attr, char *buffer)
3413 {
3414         ssize_t count = 0;
3415         mutex_lock(&spic_dev.lock);
3416         count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power);
3417         mutex_unlock(&spic_dev.lock);
3418         return count;
3419 }
3420
3421 /* fan speed */
3422 /* FAN0 information (reverse engineered from ACPI tables) */
3423 #define SONY_PIC_FAN0_STATUS    0x93
3424 static int sony_pic_set_fanspeed(unsigned long value)
3425 {
3426         return ec_write(SONY_PIC_FAN0_STATUS, value);
3427 }
3428
3429 static int sony_pic_get_fanspeed(u8 *value)
3430 {
3431         return ec_read(SONY_PIC_FAN0_STATUS, value);
3432 }
3433
3434 static ssize_t sony_pic_fanspeed_store(struct device *dev,
3435                 struct device_attribute *attr,
3436                 const char *buffer, size_t count)
3437 {
3438         unsigned long value;
3439         if (count > 31)
3440                 return -EINVAL;
3441
3442         if (kstrtoul(buffer, 10, &value))
3443                 return -EINVAL;
3444
3445         if (sony_pic_set_fanspeed(value))
3446                 return -EIO;
3447
3448         return count;
3449 }
3450
3451 static ssize_t sony_pic_fanspeed_show(struct device *dev,
3452                 struct device_attribute *attr, char *buffer)
3453 {
3454         u8 value = 0;
3455         if (sony_pic_get_fanspeed(&value))
3456                 return -EIO;
3457
3458         return snprintf(buffer, PAGE_SIZE, "%d\n", value);
3459 }
3460
3461 #define SPIC_ATTR(_name, _mode)                                 \
3462 struct device_attribute spic_attr_##_name = __ATTR(_name,       \
3463                 _mode, sony_pic_## _name ##_show,               \
3464                 sony_pic_## _name ##_store)
3465
3466 static SPIC_ATTR(bluetoothpower, 0644);
3467 static SPIC_ATTR(wwanpower, 0644);
3468 static SPIC_ATTR(fanspeed, 0644);
3469
3470 static struct attribute *spic_attributes[] = {
3471         &spic_attr_bluetoothpower.attr,
3472         &spic_attr_wwanpower.attr,
3473         &spic_attr_fanspeed.attr,
3474         NULL
3475 };
3476
3477 static struct attribute_group spic_attribute_group = {
3478         .attrs = spic_attributes
3479 };
3480
3481 /******** SONYPI compatibility **********/
3482 #ifdef CONFIG_SONYPI_COMPAT
3483
3484 /* battery / brightness / temperature  addresses */
3485 #define SONYPI_BAT_FLAGS        0x81
3486 #define SONYPI_LCD_LIGHT        0x96
3487 #define SONYPI_BAT1_PCTRM       0xa0
3488 #define SONYPI_BAT1_LEFT        0xa2
3489 #define SONYPI_BAT1_MAXRT       0xa4
3490 #define SONYPI_BAT2_PCTRM       0xa8
3491 #define SONYPI_BAT2_LEFT        0xaa
3492 #define SONYPI_BAT2_MAXRT       0xac
3493 #define SONYPI_BAT1_MAXTK       0xb0
3494 #define SONYPI_BAT1_FULL        0xb2
3495 #define SONYPI_BAT2_MAXTK       0xb8
3496 #define SONYPI_BAT2_FULL        0xba
3497 #define SONYPI_TEMP_STATUS      0xC1
3498
3499 struct sonypi_compat_s {
3500         struct fasync_struct    *fifo_async;
3501         struct kfifo            fifo;
3502         spinlock_t              fifo_lock;
3503         wait_queue_head_t       fifo_proc_list;
3504         atomic_t                open_count;
3505 };
3506 static struct sonypi_compat_s sonypi_compat = {
3507         .open_count = ATOMIC_INIT(0),
3508 };
3509
3510 static int sonypi_misc_fasync(int fd, struct file *filp, int on)
3511 {
3512         return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
3513 }
3514
3515 static int sonypi_misc_release(struct inode *inode, struct file *file)
3516 {
3517         atomic_dec(&sonypi_compat.open_count);
3518         return 0;
3519 }
3520
3521 static int sonypi_misc_open(struct inode *inode, struct file *file)
3522 {
3523         /* Flush input queue on first open */
3524         unsigned long flags;
3525
3526         spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
3527
3528         if (atomic_inc_return(&sonypi_compat.open_count) == 1)
3529                 kfifo_reset(&sonypi_compat.fifo);
3530
3531         spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
3532
3533         return 0;
3534 }
3535
3536 static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
3537                                 size_t count, loff_t *pos)
3538 {
3539         ssize_t ret;
3540         unsigned char c;
3541
3542         if ((kfifo_len(&sonypi_compat.fifo) == 0) &&
3543             (file->f_flags & O_NONBLOCK))
3544                 return -EAGAIN;
3545
3546         ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
3547                                        kfifo_len(&sonypi_compat.fifo) != 0);
3548         if (ret)
3549                 return ret;
3550
3551         while (ret < count &&
3552                (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c),
3553                           &sonypi_compat.fifo_lock) == sizeof(c))) {
3554                 if (put_user(c, buf++))
3555                         return -EFAULT;
3556                 ret++;
3557         }
3558
3559         if (ret > 0) {
3560                 struct inode *inode = file->f_path.dentry->d_inode;
3561                 inode->i_atime = current_fs_time(inode->i_sb);
3562         }
3563
3564         return ret;
3565 }
3566
3567 static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
3568 {
3569         poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
3570         if (kfifo_len(&sonypi_compat.fifo))
3571                 return POLLIN | POLLRDNORM;
3572         return 0;
3573 }
3574
3575 static int ec_read16(u8 addr, u16 *value)
3576 {
3577         u8 val_lb, val_hb;
3578         if (ec_read(addr, &val_lb))
3579                 return -1;
3580         if (ec_read(addr + 1, &val_hb))
3581                 return -1;
3582         *value = val_lb | (val_hb << 8);
3583         return 0;
3584 }
3585
3586 static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
3587                                                         unsigned long arg)
3588 {
3589         int ret = 0;
3590         void __user *argp = (void __user *)arg;
3591         u8 val8;
3592         u16 val16;
3593         int value;
3594
3595         mutex_lock(&spic_dev.lock);
3596         switch (cmd) {
3597         case SONYPI_IOCGBRT:
3598                 if (sony_bl_props.dev == NULL) {
3599                         ret = -EIO;
3600                         break;
3601                 }
3602                 if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL,
3603                                         &value)) {
3604                         ret = -EIO;
3605                         break;
3606                 }
3607                 val8 = ((value & 0xff) - 1) << 5;
3608                 if (copy_to_user(argp, &val8, sizeof(val8)))
3609                                 ret = -EFAULT;
3610                 break;
3611         case SONYPI_IOCSBRT:
3612                 if (sony_bl_props.dev == NULL) {
3613                         ret = -EIO;
3614                         break;
3615                 }
3616                 if (copy_from_user(&val8, argp, sizeof(val8))) {
3617                         ret = -EFAULT;
3618                         break;
3619                 }
3620                 value = (val8 >> 5) + 1;
3621                 if (sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &value,
3622                                         NULL)) {
3623                         ret = -EIO;
3624                         break;
3625                 }
3626                 /* sync the backlight device status */
3627                 sony_bl_props.dev->props.brightness =
3628                     sony_backlight_get_brightness(sony_bl_props.dev);
3629                 break;
3630         case SONYPI_IOCGBAT1CAP:
3631                 if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
3632                         ret = -EIO;
3633                         break;
3634                 }
3635                 if (copy_to_user(argp, &val16, sizeof(val16)))
3636                         ret = -EFAULT;
3637                 break;
3638         case SONYPI_IOCGBAT1REM:
3639                 if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
3640                         ret = -EIO;
3641                         break;
3642                 }
3643                 if (copy_to_user(argp, &val16, sizeof(val16)))
3644                         ret = -EFAULT;
3645                 break;
3646         case SONYPI_IOCGBAT2CAP:
3647                 if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
3648                         ret = -EIO;
3649                         break;
3650                 }
3651                 if (copy_to_user(argp, &val16, sizeof(val16)))
3652                         ret = -EFAULT;
3653                 break;
3654         case SONYPI_IOCGBAT2REM:
3655                 if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
3656                         ret = -EIO;
3657                         break;
3658                 }
3659                 if (copy_to_user(argp, &val16, sizeof(val16)))
3660                         ret = -EFAULT;
3661                 break;
3662         case SONYPI_IOCGBATFLAGS:
3663                 if (ec_read(SONYPI_BAT_FLAGS, &val8)) {
3664                         ret = -EIO;
3665                         break;
3666                 }
3667                 val8 &= 0x07;
3668                 if (copy_to_user(argp, &val8, sizeof(val8)))
3669                         ret = -EFAULT;
3670                 break;
3671         case SONYPI_IOCGBLUE:
3672                 val8 = spic_dev.bluetooth_power;
3673                 if (copy_to_user(argp, &val8, sizeof(val8)))
3674                         ret = -EFAULT;
3675                 break;
3676         case SONYPI_IOCSBLUE:
3677                 if (copy_from_user(&val8, argp, sizeof(val8))) {
3678                         ret = -EFAULT;
3679                         break;
3680                 }
3681                 __sony_pic_set_bluetoothpower(val8);
3682                 break;
3683         /* FAN Controls */
3684         case SONYPI_IOCGFAN:
3685                 if (sony_pic_get_fanspeed(&val8)) {
3686                         ret = -EIO;
3687                         break;
3688                 }
3689                 if (copy_to_user(argp, &val8, sizeof(val8)))
3690                         ret = -EFAULT;
3691                 break;
3692         case SONYPI_IOCSFAN:
3693                 if (copy_from_user(&val8, argp, sizeof(val8))) {
3694                         ret = -EFAULT;
3695                         break;
3696                 }
3697                 if (sony_pic_set_fanspeed(val8))
3698                         ret = -EIO;
3699                 break;
3700         /* GET Temperature (useful under APM) */
3701         case SONYPI_IOCGTEMP:
3702                 if (ec_read(SONYPI_TEMP_STATUS, &val8)) {
3703                         ret = -EIO;
3704                         break;
3705                 }
3706                 if (copy_to_user(argp, &val8, sizeof(val8)))
3707                         ret = -EFAULT;
3708                 break;
3709         default:
3710                 ret = -EINVAL;
3711         }
3712         mutex_unlock(&spic_dev.lock);
3713         return ret;
3714 }
3715
3716 static const struct file_operations sonypi_misc_fops = {
3717         .owner          = THIS_MODULE,
3718         .read           = sonypi_misc_read,
3719         .poll           = sonypi_misc_poll,
3720         .open           = sonypi_misc_open,
3721         .release        = sonypi_misc_release,
3722         .fasync         = sonypi_misc_fasync,
3723         .unlocked_ioctl = sonypi_misc_ioctl,
3724         .llseek         = noop_llseek,
3725 };
3726
3727 static struct miscdevice sonypi_misc_device = {
3728         .minor          = MISC_DYNAMIC_MINOR,
3729         .name           = "sonypi",
3730         .fops           = &sonypi_misc_fops,
3731 };
3732
3733 static void sonypi_compat_report_event(u8 event)
3734 {
3735         kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event,
3736                         sizeof(event), &sonypi_compat.fifo_lock);
3737         kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
3738         wake_up_interruptible(&sonypi_compat.fifo_proc_list);
3739 }
3740
3741 static int sonypi_compat_init(void)
3742 {
3743         int error;
3744
3745         spin_lock_init(&sonypi_compat.fifo_lock);
3746         error =
3747          kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
3748         if (error) {
3749                 pr_err("kfifo_alloc failed\n");
3750                 return error;
3751         }
3752
3753         init_waitqueue_head(&sonypi_compat.fifo_proc_list);
3754
3755         if (minor != -1)
3756                 sonypi_misc_device.minor = minor;
3757         error = misc_register(&sonypi_misc_device);
3758         if (error) {
3759                 pr_err("misc_register failed\n");
3760                 goto err_free_kfifo;
3761         }
3762         if (minor == -1)
3763                 pr_info("device allocated minor is %d\n",
3764                         sonypi_misc_device.minor);
3765
3766         return 0;
3767
3768 err_free_kfifo:
3769         kfifo_free(&sonypi_compat.fifo);
3770         return error;
3771 }
3772
3773 static void sonypi_compat_exit(void)
3774 {
3775         misc_deregister(&sonypi_misc_device);
3776         kfifo_free(&sonypi_compat.fifo);
3777 }
3778 #else
3779 static int sonypi_compat_init(void) { return 0; }
3780 static void sonypi_compat_exit(void) { }
3781 static void sonypi_compat_report_event(u8 event) { }
3782 #endif /* CONFIG_SONYPI_COMPAT */
3783
3784 /*
3785  * ACPI callbacks
3786  */
3787 static acpi_status
3788 sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
3789 {
3790         u32 i;
3791         struct sony_pic_dev *dev = (struct sony_pic_dev *)context;
3792
3793         switch (resource->type) {
3794         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
3795                 {
3796                         /* start IO enumeration */
3797                         struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
3798                         if (!ioport)
3799                                 return AE_ERROR;
3800
3801                         list_add(&ioport->list, &dev->ioports);
3802                         return AE_OK;
3803                 }
3804
3805         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
3806                 /* end IO enumeration */
3807                 return AE_OK;
3808
3809         case ACPI_RESOURCE_TYPE_IRQ:
3810                 {
3811                         struct acpi_resource_irq *p = &resource->data.irq;
3812                         struct sony_pic_irq *interrupt = NULL;
3813                         if (!p || !p->interrupt_count) {
3814                                 /*
3815                                  * IRQ descriptors may have no IRQ# bits set,
3816                                  * particularly those those w/ _STA disabled
3817                                  */
3818                                 dprintk("Blank IRQ resource\n");
3819                                 return AE_OK;
3820                         }
3821                         for (i = 0; i < p->interrupt_count; i++) {
3822                                 if (!p->interrupts[i]) {
3823                                         pr_warn("Invalid IRQ %d\n",
3824                                                 p->interrupts[i]);
3825                                         continue;
3826                                 }
3827                                 interrupt = kzalloc(sizeof(*interrupt),
3828                                                 GFP_KERNEL);
3829                                 if (!interrupt)
3830                                         return AE_ERROR;
3831
3832                                 list_add(&interrupt->list, &dev->interrupts);
3833                                 interrupt->irq.triggering = p->triggering;
3834                                 interrupt->irq.polarity = p->polarity;
3835                                 interrupt->irq.sharable = p->sharable;
3836                                 interrupt->irq.interrupt_count = 1;
3837                                 interrupt->irq.interrupts[0] = p->interrupts[i];
3838                         }
3839                         return AE_OK;
3840                 }
3841         case ACPI_RESOURCE_TYPE_IO:
3842                 {
3843                         struct acpi_resource_io *io = &resource->data.io;
3844                         struct sony_pic_ioport *ioport =
3845                                 list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
3846                         if (!io) {
3847                                 dprintk("Blank IO resource\n");
3848                                 return AE_OK;
3849                         }
3850
3851                         if (!ioport->io1.minimum) {
3852                                 memcpy(&ioport->io1, io, sizeof(*io));
3853                                 dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
3854                                                 ioport->io1.address_length);
3855                         }
3856                         else if (!ioport->io2.minimum) {
3857                                 memcpy(&ioport->io2, io, sizeof(*io));
3858                                 dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
3859                                                 ioport->io2.address_length);
3860                         }
3861                         else {
3862                                 pr_err("Unknown SPIC Type, more than 2 IO Ports\n");
3863                                 return AE_ERROR;
3864                         }
3865                         return AE_OK;
3866                 }
3867         default:
3868                 dprintk("Resource %d isn't an IRQ nor an IO port\n",
3869                         resource->type);
3870
3871         case ACPI_RESOURCE_TYPE_END_TAG:
3872                 return AE_OK;
3873         }
3874         return AE_CTRL_TERMINATE;
3875 }
3876
3877 static int sony_pic_possible_resources(struct acpi_device *device)
3878 {
3879         int result = 0;
3880         acpi_status status = AE_OK;
3881
3882         if (!device)
3883                 return -EINVAL;
3884
3885         /* get device status */
3886         /* see acpi_pci_link_get_current acpi_pci_link_get_possible */
3887         dprintk("Evaluating _STA\n");
3888         result = acpi_bus_get_status(device);
3889         if (result) {
3890                 pr_warn("Unable to read status\n");
3891                 goto end;
3892         }
3893
3894         if (!device->status.enabled)
3895                 dprintk("Device disabled\n");
3896         else
3897                 dprintk("Device enabled\n");
3898
3899         /*
3900          * Query and parse 'method'
3901          */
3902         dprintk("Evaluating %s\n", METHOD_NAME__PRS);
3903         status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
3904                         sony_pic_read_possible_resource, &spic_dev);
3905         if (ACPI_FAILURE(status)) {
3906                 pr_warn("Failure evaluating %s\n", METHOD_NAME__PRS);
3907                 result = -ENODEV;
3908         }
3909 end:
3910         return result;
3911 }
3912
3913 /*
3914  *  Disable the spic device by calling its _DIS method
3915  */
3916 static int sony_pic_disable(struct acpi_device *device)
3917 {
3918         acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL,
3919                                                NULL);
3920
3921         if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND)
3922                 return -ENXIO;
3923
3924         dprintk("Device disabled\n");
3925         return 0;
3926 }
3927
3928
3929 /*
3930  *  Based on drivers/acpi/pci_link.c:acpi_pci_link_set
3931  *
3932  *  Call _SRS to set current resources
3933  */
3934 static int sony_pic_enable(struct acpi_device *device,
3935                 struct sony_pic_ioport *ioport, struct sony_pic_irq *irq)
3936 {
3937         acpi_status status;
3938         int result = 0;
3939         /* Type 1 resource layout is:
3940          *    IO
3941          *    IO
3942          *    IRQNoFlags
3943          *    End
3944          *
3945          * Type 2 and 3 resource layout is:
3946          *    IO
3947          *    IRQNoFlags
3948          *    End
3949          */
3950         struct {
3951                 struct acpi_resource res1;
3952                 struct acpi_resource res2;
3953                 struct acpi_resource res3;
3954                 struct acpi_resource res4;
3955         } *resource;
3956         struct acpi_buffer buffer = { 0, NULL };
3957
3958         if (!ioport || !irq)
3959                 return -EINVAL;
3960
3961         /* init acpi_buffer */
3962         resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
3963         if (!resource)
3964                 return -ENOMEM;
3965
3966         buffer.length = sizeof(*resource) + 1;
3967         buffer.pointer = resource;
3968
3969         /* setup Type 1 resources */
3970         if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
3971
3972                 /* setup io resources */
3973                 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
3974                 resource->res1.length = sizeof(struct acpi_resource);
3975                 memcpy(&resource->res1.data.io, &ioport->io1,
3976                                 sizeof(struct acpi_resource_io));
3977
3978                 resource->res2.type = ACPI_RESOURCE_TYPE_IO;
3979                 resource->res2.length = sizeof(struct acpi_resource);
3980                 memcpy(&resource->res2.data.io, &ioport->io2,
3981                                 sizeof(struct acpi_resource_io));
3982
3983                 /* setup irq resource */
3984                 resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
3985                 resource->res3.length = sizeof(struct acpi_resource);
3986                 memcpy(&resource->res3.data.irq, &irq->irq,
3987                                 sizeof(struct acpi_resource_irq));
3988                 /* we requested a shared irq */
3989                 resource->res3.data.irq.sharable = ACPI_SHARED;
3990
3991                 resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
3992
3993         }
3994         /* setup Type 2/3 resources */
3995         else {
3996                 /* setup io resource */
3997                 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
3998                 resource->res1.length = sizeof(struct acpi_resource);
3999                 memcpy(&resource->res1.data.io, &ioport->io1,
4000                                 sizeof(struct acpi_resource_io));
4001
4002                 /* setup irq resource */
4003                 resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
4004                 resource->res2.length = sizeof(struct acpi_resource);
4005                 memcpy(&resource->res2.data.irq, &irq->irq,
4006                                 sizeof(struct acpi_resource_irq));
4007                 /* we requested a shared irq */
4008                 resource->res2.data.irq.sharable = ACPI_SHARED;
4009
4010                 resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
4011         }
4012
4013         /* Attempt to set the resource */
4014         dprintk("Evaluating _SRS\n");
4015         status = acpi_set_current_resources(device->handle, &buffer);
4016
4017         /* check for total failure */
4018         if (ACPI_FAILURE(status)) {
4019                 pr_err("Error evaluating _SRS\n");
4020                 result = -ENODEV;
4021                 goto end;
4022         }
4023
4024         /* Necessary device initializations calls (from sonypi) */
4025         sony_pic_call1(0x82);
4026         sony_pic_call2(0x81, 0xff);
4027         sony_pic_call1(compat ? 0x92 : 0x82);
4028
4029 end:
4030         kfree(resource);
4031         return result;
4032 }
4033
4034 /*****************
4035  *
4036  * ISR: some event is available
4037  *
4038  *****************/
4039 static irqreturn_t sony_pic_irq(int irq, void *dev_id)
4040 {
4041         int i, j;
4042         u8 ev = 0;
4043         u8 data_mask = 0;
4044         u8 device_event = 0;
4045
4046         struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
4047
4048         ev = inb_p(dev->cur_ioport->io1.minimum);
4049         if (dev->cur_ioport->io2.minimum)
4050                 data_mask = inb_p(dev->cur_ioport->io2.minimum);
4051         else
4052                 data_mask = inb_p(dev->cur_ioport->io1.minimum +
4053                                 dev->evport_offset);
4054
4055         dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
4056                         ev, data_mask, dev->cur_ioport->io1.minimum,
4057                         dev->evport_offset);
4058
4059         if (ev == 0x00 || ev == 0xff)
4060                 return IRQ_HANDLED;
4061
4062         for (i = 0; dev->event_types[i].mask; i++) {
4063
4064                 if ((data_mask & dev->event_types[i].data) !=
4065                     dev->event_types[i].data)
4066                         continue;
4067
4068                 if (!(mask & dev->event_types[i].mask))
4069                         continue;
4070
4071                 for (j = 0; dev->event_types[i].events[j].event; j++) {
4072                         if (ev == dev->event_types[i].events[j].data) {
4073                                 device_event =
4074                                         dev->event_types[i].events[j].event;
4075                                 /* some events may require ignoring */
4076                                 if (!device_event)
4077                                         return IRQ_HANDLED;
4078                                 goto found;
4079                         }
4080                 }
4081         }
4082         /* Still not able to decode the event try to pass
4083          * it over to the minidriver
4084          */
4085         if (dev->handle_irq && dev->handle_irq(data_mask, ev) == 0)
4086                 return IRQ_HANDLED;
4087
4088         dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
4089                         ev, data_mask, dev->cur_ioport->io1.minimum,
4090                         dev->evport_offset);
4091         return IRQ_HANDLED;
4092
4093 found:
4094         sony_laptop_report_input_event(device_event);
4095         acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
4096         sonypi_compat_report_event(device_event);
4097         return IRQ_HANDLED;
4098 }
4099
4100 /*****************
4101  *
4102  *  ACPI driver
4103  *
4104  *****************/
4105 static int sony_pic_remove(struct acpi_device *device, int type)
4106 {
4107         struct sony_pic_ioport *io, *tmp_io;
4108         struct sony_pic_irq *irq, *tmp_irq;
4109
4110         if (sony_pic_disable(device)) {
4111                 pr_err("Couldn't disable device\n");
4112                 return -ENXIO;
4113         }
4114
4115         free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
4116         release_region(spic_dev.cur_ioport->io1.minimum,
4117                         spic_dev.cur_ioport->io1.address_length);
4118         if (spic_dev.cur_ioport->io2.minimum)
4119                 release_region(spic_dev.cur_ioport->io2.minimum,
4120                                 spic_dev.cur_ioport->io2.address_length);
4121
4122         sonypi_compat_exit();
4123
4124         sony_laptop_remove_input();
4125
4126         /* pf attrs */
4127         sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
4128         sony_pf_remove();
4129
4130         list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
4131                 list_del(&io->list);
4132                 kfree(io);
4133         }
4134         list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
4135                 list_del(&irq->list);
4136                 kfree(irq);
4137         }
4138         spic_dev.cur_ioport = NULL;
4139         spic_dev.cur_irq = NULL;
4140
4141         dprintk(SONY_PIC_DRIVER_NAME " removed.\n");
4142         return 0;
4143 }
4144
4145 static int sony_pic_add(struct acpi_device *device)
4146 {
4147         int result;
4148         struct sony_pic_ioport *io, *tmp_io;
4149         struct sony_pic_irq *irq, *tmp_irq;
4150
4151         pr_info("%s v%s\n", SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
4152
4153         spic_dev.acpi_dev = device;
4154         strcpy(acpi_device_class(device), "sony/hotkey");
4155         sony_pic_detect_device_type(&spic_dev);
4156         mutex_init(&spic_dev.lock);
4157
4158         /* read _PRS resources */
4159         result = sony_pic_possible_resources(device);
4160         if (result) {
4161                 pr_err("Unable to read possible resources\n");
4162                 goto err_free_resources;
4163         }
4164
4165         /* setup input devices and helper fifo */
4166         result = sony_laptop_setup_input(device);
4167         if (result) {
4168                 pr_err("Unable to create input devices\n");
4169                 goto err_free_resources;
4170         }
4171
4172         if (sonypi_compat_init())
4173                 goto err_remove_input;
4174
4175         /* request io port */
4176         list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
4177                 if (request_region(io->io1.minimum, io->io1.address_length,
4178                                         "Sony Programmable I/O Device")) {
4179                         dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
4180                                         io->io1.minimum, io->io1.maximum,
4181                                         io->io1.address_length);
4182                         /* Type 1 have 2 ioports */
4183                         if (io->io2.minimum) {
4184                                 if (request_region(io->io2.minimum,
4185                                                 io->io2.address_length,
4186                                                 "Sony Programmable I/O Device")) {
4187                                         dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
4188                                                         io->io2.minimum, io->io2.maximum,
4189                                                         io->io2.address_length);
4190                                         spic_dev.cur_ioport = io;
4191                                         break;
4192                                 }
4193                                 else {
4194                                         dprintk("Unable to get I/O port2: "
4195                                                         "0x%.4x (0x%.4x) + 0x%.2x\n",
4196                                                         io->io2.minimum, io->io2.maximum,
4197                                                         io->io2.address_length);
4198                                         release_region(io->io1.minimum,
4199                                                         io->io1.address_length);
4200                                 }
4201                         }
4202                         else {
4203                                 spic_dev.cur_ioport = io;
4204                                 break;
4205                         }
4206                 }
4207         }
4208         if (!spic_dev.cur_ioport) {
4209                 pr_err("Failed to request_region\n");
4210                 result = -ENODEV;
4211                 goto err_remove_compat;
4212         }
4213
4214         /* request IRQ */
4215         list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
4216                 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
4217                                         0, "sony-laptop", &spic_dev)) {
4218                         dprintk("IRQ: %d - triggering: %d - "
4219                                         "polarity: %d - shr: %d\n",
4220                                         irq->irq.interrupts[0],
4221                                         irq->irq.triggering,
4222                                         irq->irq.polarity,
4223                                         irq->irq.sharable);
4224                         spic_dev.cur_irq = irq;
4225                         break;
4226                 }
4227         }
4228         if (!spic_dev.cur_irq) {
4229                 pr_err("Failed to request_irq\n");
4230                 result = -ENODEV;
4231                 goto err_release_region;
4232         }
4233
4234         /* set resource status _SRS */
4235         result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
4236         if (result) {
4237                 pr_err("Couldn't enable device\n");
4238                 goto err_free_irq;
4239         }
4240
4241         spic_dev.bluetooth_power = -1;
4242         /* create device attributes */
4243         result = sony_pf_add();
4244         if (result)
4245                 goto err_disable_device;
4246
4247         result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
4248         if (result)
4249                 goto err_remove_pf;
4250
4251         return 0;
4252
4253 err_remove_pf:
4254         sony_pf_remove();
4255
4256 err_disable_device:
4257         sony_pic_disable(device);
4258
4259 err_free_irq:
4260         free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
4261
4262 err_release_region:
4263         release_region(spic_dev.cur_ioport->io1.minimum,
4264                         spic_dev.cur_ioport->io1.address_length);
4265         if (spic_dev.cur_ioport->io2.minimum)
4266                 release_region(spic_dev.cur_ioport->io2.minimum,
4267                                 spic_dev.cur_ioport->io2.address_length);
4268
4269 err_remove_compat:
4270         sonypi_compat_exit();
4271
4272 err_remove_input:
4273         sony_laptop_remove_input();
4274
4275 err_free_resources:
4276         list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
4277                 list_del(&io->list);
4278                 kfree(io);
4279         }
4280         list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
4281                 list_del(&irq->list);
4282                 kfree(irq);
4283         }
4284         spic_dev.cur_ioport = NULL;
4285         spic_dev.cur_irq = NULL;
4286
4287         return result;
4288 }
4289
4290 static int sony_pic_suspend(struct device *dev)
4291 {
4292         if (sony_pic_disable(to_acpi_device(dev)))
4293                 return -ENXIO;
4294         return 0;
4295 }
4296
4297 static int sony_pic_resume(struct device *dev)
4298 {
4299         sony_pic_enable(to_acpi_device(dev),
4300                         spic_dev.cur_ioport, spic_dev.cur_irq);
4301         return 0;
4302 }
4303
4304 static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume);
4305
4306 static const struct acpi_device_id sony_pic_device_ids[] = {
4307         {SONY_PIC_HID, 0},
4308         {"", 0},
4309 };
4310
4311 static struct acpi_driver sony_pic_driver = {
4312         .name = SONY_PIC_DRIVER_NAME,
4313         .class = SONY_PIC_CLASS,
4314         .ids = sony_pic_device_ids,
4315         .owner = THIS_MODULE,
4316         .ops = {
4317                 .add = sony_pic_add,
4318                 .remove = sony_pic_remove,
4319                 },
4320         .drv.pm = &sony_pic_pm,
4321 };
4322
4323 static struct dmi_system_id __initdata sonypi_dmi_table[] = {
4324         {
4325                 .ident = "Sony Vaio",
4326                 .matches = {
4327                         DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
4328                         DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"),
4329                 },
4330         },
4331         {
4332                 .ident = "Sony Vaio",
4333                 .matches = {
4334                         DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
4335                         DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
4336                 },
4337         },
4338         { }
4339 };
4340
4341 static int __init sony_laptop_init(void)
4342 {
4343         int result;
4344
4345         if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
4346                 result = acpi_bus_register_driver(&sony_pic_driver);
4347                 if (result) {
4348                         pr_err("Unable to register SPIC driver\n");
4349                         goto out;
4350                 }
4351                 spic_drv_registered = 1;
4352         }
4353
4354         result = acpi_bus_register_driver(&sony_nc_driver);
4355         if (result) {
4356                 pr_err("Unable to register SNC driver\n");
4357                 goto out_unregister_pic;
4358         }
4359
4360         return 0;
4361
4362 out_unregister_pic:
4363         if (spic_drv_registered)
4364                 acpi_bus_unregister_driver(&sony_pic_driver);
4365 out:
4366         return result;
4367 }
4368
4369 static void __exit sony_laptop_exit(void)
4370 {
4371         acpi_bus_unregister_driver(&sony_nc_driver);
4372         if (spic_drv_registered)
4373                 acpi_bus_unregister_driver(&sony_pic_driver);
4374 }
4375
4376 module_init(sony_laptop_init);
4377 module_exit(sony_laptop_exit);