]> Pileus Git - ~andy/linux/blob - drivers/platform/x86/sony-laptop.c
Merge branch 'x86-reboot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[~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 acpi_device *device)
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 void sony_nc_rfkill_cleanup(void)
1513 {
1514         int i;
1515
1516         for (i = 0; i < N_SONY_RFKILL; i++) {
1517                 if (sony_rfkill_devices[i]) {
1518                         rfkill_unregister(sony_rfkill_devices[i]);
1519                         rfkill_destroy(sony_rfkill_devices[i]);
1520                 }
1521         }
1522 }
1523
1524 static int sony_nc_rfkill_set(void *data, bool blocked)
1525 {
1526         int result;
1527         int argument = sony_rfkill_address[(long) data] + 0x100;
1528
1529         if (!blocked)
1530                 argument |= 0x030000;
1531
1532         return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1533 }
1534
1535 static const struct rfkill_ops sony_rfkill_ops = {
1536         .set_block = sony_nc_rfkill_set,
1537 };
1538
1539 static int sony_nc_setup_rfkill(struct acpi_device *device,
1540                                 enum sony_nc_rfkill nc_type)
1541 {
1542         int err = 0;
1543         struct rfkill *rfk;
1544         enum rfkill_type type;
1545         const char *name;
1546         int result;
1547         bool hwblock, swblock;
1548
1549         switch (nc_type) {
1550         case SONY_WIFI:
1551                 type = RFKILL_TYPE_WLAN;
1552                 name = "sony-wifi";
1553                 break;
1554         case SONY_BLUETOOTH:
1555                 type = RFKILL_TYPE_BLUETOOTH;
1556                 name = "sony-bluetooth";
1557                 break;
1558         case SONY_WWAN:
1559                 type = RFKILL_TYPE_WWAN;
1560                 name = "sony-wwan";
1561                 break;
1562         case SONY_WIMAX:
1563                 type = RFKILL_TYPE_WIMAX;
1564                 name = "sony-wimax";
1565                 break;
1566         default:
1567                 return -EINVAL;
1568         }
1569
1570         rfk = rfkill_alloc(name, &device->dev, type,
1571                            &sony_rfkill_ops, (void *)nc_type);
1572         if (!rfk)
1573                 return -ENOMEM;
1574
1575         if (sony_call_snc_handle(sony_rfkill_handle, 0x200, &result) < 0) {
1576                 rfkill_destroy(rfk);
1577                 return -1;
1578         }
1579         hwblock = !(result & 0x1);
1580
1581         if (sony_call_snc_handle(sony_rfkill_handle,
1582                                 sony_rfkill_address[nc_type],
1583                                 &result) < 0) {
1584                 rfkill_destroy(rfk);
1585                 return -1;
1586         }
1587         swblock = !(result & 0x2);
1588
1589         rfkill_init_sw_state(rfk, swblock);
1590         rfkill_set_hw_state(rfk, hwblock);
1591
1592         err = rfkill_register(rfk);
1593         if (err) {
1594                 rfkill_destroy(rfk);
1595                 return err;
1596         }
1597         sony_rfkill_devices[nc_type] = rfk;
1598         return err;
1599 }
1600
1601 static void sony_nc_rfkill_update(void)
1602 {
1603         enum sony_nc_rfkill i;
1604         int result;
1605         bool hwblock;
1606
1607         sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1608         hwblock = !(result & 0x1);
1609
1610         for (i = 0; i < N_SONY_RFKILL; i++) {
1611                 int argument = sony_rfkill_address[i];
1612
1613                 if (!sony_rfkill_devices[i])
1614                         continue;
1615
1616                 if (hwblock) {
1617                         if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
1618                                 /* we already know we're blocked */
1619                         }
1620                         continue;
1621                 }
1622
1623                 sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1624                 rfkill_set_states(sony_rfkill_devices[i],
1625                                   !(result & 0x2), false);
1626         }
1627 }
1628
1629 static int sony_nc_rfkill_setup(struct acpi_device *device,
1630                 unsigned int handle)
1631 {
1632         u64 offset;
1633         int i;
1634         unsigned char buffer[32] = { 0 };
1635
1636         offset = sony_find_snc_handle(handle);
1637         sony_rfkill_handle = handle;
1638
1639         i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer,
1640                         32);
1641         if (i < 0)
1642                 return i;
1643
1644         /* The buffer is filled with magic numbers describing the devices
1645          * available, 0xff terminates the enumeration.
1646          * Known codes:
1647          *      0x00 WLAN
1648          *      0x10 BLUETOOTH
1649          *      0x20 WWAN GPRS-EDGE
1650          *      0x21 WWAN HSDPA
1651          *      0x22 WWAN EV-DO
1652          *      0x23 WWAN GPS
1653          *      0x25 Gobi WWAN no GPS
1654          *      0x26 Gobi WWAN + GPS
1655          *      0x28 Gobi WWAN no GPS
1656          *      0x29 Gobi WWAN + GPS
1657          *      0x30 WIMAX
1658          *      0x50 Gobi WWAN no GPS
1659          *      0x51 Gobi WWAN + GPS
1660          *      0x70 no SIM card slot
1661          *      0x71 SIM card slot
1662          */
1663         for (i = 0; i < ARRAY_SIZE(buffer); i++) {
1664
1665                 if (buffer[i] == 0xff)
1666                         break;
1667
1668                 dprintk("Radio devices, found 0x%.2x\n", buffer[i]);
1669
1670                 if (buffer[i] == 0 && !sony_rfkill_devices[SONY_WIFI])
1671                         sony_nc_setup_rfkill(device, SONY_WIFI);
1672
1673                 if (buffer[i] == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
1674                         sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1675
1676                 if (((0xf0 & buffer[i]) == 0x20 ||
1677                                         (0xf0 & buffer[i]) == 0x50) &&
1678                                 !sony_rfkill_devices[SONY_WWAN])
1679                         sony_nc_setup_rfkill(device, SONY_WWAN);
1680
1681                 if (buffer[i] == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
1682                         sony_nc_setup_rfkill(device, SONY_WIMAX);
1683         }
1684         return 0;
1685 }
1686
1687 /* Keyboard backlight feature */
1688 struct kbd_backlight {
1689         unsigned int handle;
1690         unsigned int base;
1691         unsigned int mode;
1692         unsigned int timeout;
1693         struct device_attribute mode_attr;
1694         struct device_attribute timeout_attr;
1695 };
1696
1697 static struct kbd_backlight *kbdbl_ctl;
1698
1699 static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
1700 {
1701         int result;
1702
1703         if (value > 1)
1704                 return -EINVAL;
1705
1706         if (sony_call_snc_handle(kbdbl_ctl->handle,
1707                                 (value << 0x10) | (kbdbl_ctl->base), &result))
1708                 return -EIO;
1709
1710         /* Try to turn the light on/off immediately */
1711         sony_call_snc_handle(kbdbl_ctl->handle,
1712                         (value << 0x10) | (kbdbl_ctl->base + 0x100), &result);
1713
1714         kbdbl_ctl->mode = value;
1715
1716         return 0;
1717 }
1718
1719 static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
1720                 struct device_attribute *attr,
1721                 const char *buffer, size_t count)
1722 {
1723         int ret = 0;
1724         unsigned long value;
1725
1726         if (count > 31)
1727                 return -EINVAL;
1728
1729         if (kstrtoul(buffer, 10, &value))
1730                 return -EINVAL;
1731
1732         ret = __sony_nc_kbd_backlight_mode_set(value);
1733         if (ret < 0)
1734                 return ret;
1735
1736         return count;
1737 }
1738
1739 static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
1740                 struct device_attribute *attr, char *buffer)
1741 {
1742         ssize_t count = 0;
1743         count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->mode);
1744         return count;
1745 }
1746
1747 static int __sony_nc_kbd_backlight_timeout_set(u8 value)
1748 {
1749         int result;
1750
1751         if (value > 3)
1752                 return -EINVAL;
1753
1754         if (sony_call_snc_handle(kbdbl_ctl->handle, (value << 0x10) |
1755                                 (kbdbl_ctl->base + 0x200), &result))
1756                 return -EIO;
1757
1758         kbdbl_ctl->timeout = value;
1759
1760         return 0;
1761 }
1762
1763 static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
1764                 struct device_attribute *attr,
1765                 const char *buffer, size_t count)
1766 {
1767         int ret = 0;
1768         unsigned long value;
1769
1770         if (count > 31)
1771                 return -EINVAL;
1772
1773         if (kstrtoul(buffer, 10, &value))
1774                 return -EINVAL;
1775
1776         ret = __sony_nc_kbd_backlight_timeout_set(value);
1777         if (ret < 0)
1778                 return ret;
1779
1780         return count;
1781 }
1782
1783 static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
1784                 struct device_attribute *attr, char *buffer)
1785 {
1786         ssize_t count = 0;
1787         count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->timeout);
1788         return count;
1789 }
1790
1791 static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
1792                 unsigned int handle)
1793 {
1794         int result;
1795         int ret = 0;
1796
1797         /* verify the kbd backlight presence, these handles are not used for
1798          * keyboard backlight only
1799          */
1800         ret = sony_call_snc_handle(handle, handle == 0x0137 ? 0x0B00 : 0x0100,
1801                         &result);
1802         if (ret)
1803                 return ret;
1804
1805         if ((handle == 0x0137 && !(result & 0x02)) ||
1806                         !(result & 0x01)) {
1807                 dprintk("no backlight keyboard found\n");
1808                 return 0;
1809         }
1810
1811         kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL);
1812         if (!kbdbl_ctl)
1813                 return -ENOMEM;
1814
1815         kbdbl_ctl->handle = handle;
1816         if (handle == 0x0137)
1817                 kbdbl_ctl->base = 0x0C00;
1818         else
1819                 kbdbl_ctl->base = 0x4000;
1820
1821         sysfs_attr_init(&kbdbl_ctl->mode_attr.attr);
1822         kbdbl_ctl->mode_attr.attr.name = "kbd_backlight";
1823         kbdbl_ctl->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
1824         kbdbl_ctl->mode_attr.show = sony_nc_kbd_backlight_mode_show;
1825         kbdbl_ctl->mode_attr.store = sony_nc_kbd_backlight_mode_store;
1826
1827         sysfs_attr_init(&kbdbl_ctl->timeout_attr.attr);
1828         kbdbl_ctl->timeout_attr.attr.name = "kbd_backlight_timeout";
1829         kbdbl_ctl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
1830         kbdbl_ctl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
1831         kbdbl_ctl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
1832
1833         ret = device_create_file(&pd->dev, &kbdbl_ctl->mode_attr);
1834         if (ret)
1835                 goto outkzalloc;
1836
1837         ret = device_create_file(&pd->dev, &kbdbl_ctl->timeout_attr);
1838         if (ret)
1839                 goto outmode;
1840
1841         __sony_nc_kbd_backlight_mode_set(kbd_backlight);
1842         __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
1843
1844         return 0;
1845
1846 outmode:
1847         device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
1848 outkzalloc:
1849         kfree(kbdbl_ctl);
1850         kbdbl_ctl = NULL;
1851         return ret;
1852 }
1853
1854 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
1855 {
1856         if (kbdbl_ctl) {
1857                 int result;
1858
1859                 device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
1860                 device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr);
1861
1862                 /* restore the default hw behaviour */
1863                 sony_call_snc_handle(kbdbl_ctl->handle,
1864                                 kbdbl_ctl->base | 0x10000, &result);
1865                 sony_call_snc_handle(kbdbl_ctl->handle,
1866                                 kbdbl_ctl->base + 0x200, &result);
1867
1868                 kfree(kbdbl_ctl);
1869                 kbdbl_ctl = NULL;
1870         }
1871 }
1872
1873 static void sony_nc_kbd_backlight_resume(void)
1874 {
1875         int ignore = 0;
1876
1877         if (!kbdbl_ctl)
1878                 return;
1879
1880         if (kbdbl_ctl->mode == 0)
1881                 sony_call_snc_handle(kbdbl_ctl->handle, kbdbl_ctl->base,
1882                                 &ignore);
1883
1884         if (kbdbl_ctl->timeout != 0)
1885                 sony_call_snc_handle(kbdbl_ctl->handle,
1886                                 (kbdbl_ctl->base + 0x200) |
1887                                 (kbdbl_ctl->timeout << 0x10), &ignore);
1888 }
1889
1890 struct battery_care_control {
1891         struct device_attribute attrs[2];
1892         unsigned int handle;
1893 };
1894 static struct battery_care_control *bcare_ctl;
1895
1896 static ssize_t sony_nc_battery_care_limit_store(struct device *dev,
1897                 struct device_attribute *attr,
1898                 const char *buffer, size_t count)
1899 {
1900         unsigned int result, cmd;
1901         unsigned long value;
1902
1903         if (count > 31)
1904                 return -EINVAL;
1905
1906         if (kstrtoul(buffer, 10, &value))
1907                 return -EINVAL;
1908
1909         /*  limit values (2 bits):
1910          *  00 - none
1911          *  01 - 80%
1912          *  10 - 50%
1913          *  11 - 100%
1914          *
1915          *  bit 0: 0 disable BCL, 1 enable BCL
1916          *  bit 1: 1 tell to store the battery limit (see bits 6,7) too
1917          *  bits 2,3: reserved
1918          *  bits 4,5: store the limit into the EC
1919          *  bits 6,7: store the limit into the battery
1920          */
1921         cmd = 0;
1922
1923         if (value > 0) {
1924                 if (value <= 50)
1925                         cmd = 0x20;
1926
1927                 else if (value <= 80)
1928                         cmd = 0x10;
1929
1930                 else if (value <= 100)
1931                         cmd = 0x30;
1932
1933                 else
1934                         return -EINVAL;
1935
1936                 /*
1937                  * handle 0x0115 should allow storing on battery too;
1938                  * handle 0x0136 same as 0x0115 + health status;
1939                  * handle 0x013f, same as 0x0136 but no storing on the battery
1940                  */
1941                 if (bcare_ctl->handle != 0x013f)
1942                         cmd = cmd | (cmd << 2);
1943
1944                 cmd = (cmd | 0x1) << 0x10;
1945         }
1946
1947         if (sony_call_snc_handle(bcare_ctl->handle, cmd | 0x0100, &result))
1948                 return -EIO;
1949
1950         return count;
1951 }
1952
1953 static ssize_t sony_nc_battery_care_limit_show(struct device *dev,
1954                 struct device_attribute *attr, char *buffer)
1955 {
1956         unsigned int result, status;
1957
1958         if (sony_call_snc_handle(bcare_ctl->handle, 0x0000, &result))
1959                 return -EIO;
1960
1961         status = (result & 0x01) ? ((result & 0x30) >> 0x04) : 0;
1962         switch (status) {
1963         case 1:
1964                 status = 80;
1965                 break;
1966         case 2:
1967                 status = 50;
1968                 break;
1969         case 3:
1970                 status = 100;
1971                 break;
1972         default:
1973                 status = 0;
1974                 break;
1975         }
1976
1977         return snprintf(buffer, PAGE_SIZE, "%d\n", status);
1978 }
1979
1980 static ssize_t sony_nc_battery_care_health_show(struct device *dev,
1981                 struct device_attribute *attr, char *buffer)
1982 {
1983         ssize_t count = 0;
1984         unsigned int health;
1985
1986         if (sony_call_snc_handle(bcare_ctl->handle, 0x0200, &health))
1987                 return -EIO;
1988
1989         count = snprintf(buffer, PAGE_SIZE, "%d\n", health & 0xff);
1990
1991         return count;
1992 }
1993
1994 static int sony_nc_battery_care_setup(struct platform_device *pd,
1995                 unsigned int handle)
1996 {
1997         int ret = 0;
1998
1999         bcare_ctl = kzalloc(sizeof(struct battery_care_control), GFP_KERNEL);
2000         if (!bcare_ctl)
2001                 return -ENOMEM;
2002
2003         bcare_ctl->handle = handle;
2004
2005         sysfs_attr_init(&bcare_ctl->attrs[0].attr);
2006         bcare_ctl->attrs[0].attr.name = "battery_care_limiter";
2007         bcare_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR;
2008         bcare_ctl->attrs[0].show = sony_nc_battery_care_limit_show;
2009         bcare_ctl->attrs[0].store = sony_nc_battery_care_limit_store;
2010
2011         ret = device_create_file(&pd->dev, &bcare_ctl->attrs[0]);
2012         if (ret)
2013                 goto outkzalloc;
2014
2015         /* 0x0115 is for models with no health reporting capability */
2016         if (handle == 0x0115)
2017                 return 0;
2018
2019         sysfs_attr_init(&bcare_ctl->attrs[1].attr);
2020         bcare_ctl->attrs[1].attr.name = "battery_care_health";
2021         bcare_ctl->attrs[1].attr.mode = S_IRUGO;
2022         bcare_ctl->attrs[1].show = sony_nc_battery_care_health_show;
2023
2024         ret = device_create_file(&pd->dev, &bcare_ctl->attrs[1]);
2025         if (ret)
2026                 goto outlimiter;
2027
2028         return 0;
2029
2030 outlimiter:
2031         device_remove_file(&pd->dev, &bcare_ctl->attrs[0]);
2032
2033 outkzalloc:
2034         kfree(bcare_ctl);
2035         bcare_ctl = NULL;
2036
2037         return ret;
2038 }
2039
2040 static void sony_nc_battery_care_cleanup(struct platform_device *pd)
2041 {
2042         if (bcare_ctl) {
2043                 device_remove_file(&pd->dev, &bcare_ctl->attrs[0]);
2044                 if (bcare_ctl->handle != 0x0115)
2045                         device_remove_file(&pd->dev, &bcare_ctl->attrs[1]);
2046
2047                 kfree(bcare_ctl);
2048                 bcare_ctl = NULL;
2049         }
2050 }
2051
2052 struct snc_thermal_ctrl {
2053         unsigned int mode;
2054         unsigned int profiles;
2055         struct device_attribute mode_attr;
2056         struct device_attribute profiles_attr;
2057 };
2058 static struct snc_thermal_ctrl *th_handle;
2059
2060 #define THM_PROFILE_MAX 3
2061 static const char * const snc_thermal_profiles[] = {
2062         "balanced",
2063         "silent",
2064         "performance"
2065 };
2066
2067 static int sony_nc_thermal_mode_set(unsigned short mode)
2068 {
2069         unsigned int result;
2070
2071         /* the thermal profile seems to be a two bit bitmask:
2072          * lsb -> silent
2073          * msb -> performance
2074          * no bit set is the normal operation and is always valid
2075          * Some vaio models only have "balanced" and "performance"
2076          */
2077         if ((mode && !(th_handle->profiles & mode)) || mode >= THM_PROFILE_MAX)
2078                 return -EINVAL;
2079
2080         if (sony_call_snc_handle(0x0122, mode << 0x10 | 0x0200, &result))
2081                 return -EIO;
2082
2083         th_handle->mode = mode;
2084
2085         return 0;
2086 }
2087
2088 static int sony_nc_thermal_mode_get(void)
2089 {
2090         unsigned int result;
2091
2092         if (sony_call_snc_handle(0x0122, 0x0100, &result))
2093                 return -EIO;
2094
2095         return result & 0xff;
2096 }
2097
2098 static ssize_t sony_nc_thermal_profiles_show(struct device *dev,
2099                 struct device_attribute *attr, char *buffer)
2100 {
2101         short cnt;
2102         size_t idx = 0;
2103
2104         for (cnt = 0; cnt < THM_PROFILE_MAX; cnt++) {
2105                 if (!cnt || (th_handle->profiles & cnt))
2106                         idx += snprintf(buffer + idx, PAGE_SIZE - idx, "%s ",
2107                                         snc_thermal_profiles[cnt]);
2108         }
2109         idx += snprintf(buffer + idx, PAGE_SIZE - idx, "\n");
2110
2111         return idx;
2112 }
2113
2114 static ssize_t sony_nc_thermal_mode_store(struct device *dev,
2115                 struct device_attribute *attr,
2116                 const char *buffer, size_t count)
2117 {
2118         unsigned short cmd;
2119         size_t len = count;
2120
2121         if (count == 0)
2122                 return -EINVAL;
2123
2124         /* skip the newline if present */
2125         if (buffer[len - 1] == '\n')
2126                 len--;
2127
2128         for (cmd = 0; cmd < THM_PROFILE_MAX; cmd++)
2129                 if (strncmp(buffer, snc_thermal_profiles[cmd], len) == 0)
2130                         break;
2131
2132         if (sony_nc_thermal_mode_set(cmd))
2133                 return -EIO;
2134
2135         return count;
2136 }
2137
2138 static ssize_t sony_nc_thermal_mode_show(struct device *dev,
2139                 struct device_attribute *attr, char *buffer)
2140 {
2141         ssize_t count = 0;
2142         int mode = sony_nc_thermal_mode_get();
2143
2144         if (mode < 0)
2145                 return mode;
2146
2147         count = snprintf(buffer, PAGE_SIZE, "%s\n", snc_thermal_profiles[mode]);
2148
2149         return count;
2150 }
2151
2152 static int sony_nc_thermal_setup(struct platform_device *pd)
2153 {
2154         int ret = 0;
2155         th_handle = kzalloc(sizeof(struct snc_thermal_ctrl), GFP_KERNEL);
2156         if (!th_handle)
2157                 return -ENOMEM;
2158
2159         ret = sony_call_snc_handle(0x0122, 0x0000, &th_handle->profiles);
2160         if (ret) {
2161                 pr_warn("couldn't to read the thermal profiles\n");
2162                 goto outkzalloc;
2163         }
2164
2165         ret = sony_nc_thermal_mode_get();
2166         if (ret < 0) {
2167                 pr_warn("couldn't to read the current thermal profile");
2168                 goto outkzalloc;
2169         }
2170         th_handle->mode = ret;
2171
2172         sysfs_attr_init(&th_handle->profiles_attr.attr);
2173         th_handle->profiles_attr.attr.name = "thermal_profiles";
2174         th_handle->profiles_attr.attr.mode = S_IRUGO;
2175         th_handle->profiles_attr.show = sony_nc_thermal_profiles_show;
2176
2177         sysfs_attr_init(&th_handle->mode_attr.attr);
2178         th_handle->mode_attr.attr.name = "thermal_control";
2179         th_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
2180         th_handle->mode_attr.show = sony_nc_thermal_mode_show;
2181         th_handle->mode_attr.store = sony_nc_thermal_mode_store;
2182
2183         ret = device_create_file(&pd->dev, &th_handle->profiles_attr);
2184         if (ret)
2185                 goto outkzalloc;
2186
2187         ret = device_create_file(&pd->dev, &th_handle->mode_attr);
2188         if (ret)
2189                 goto outprofiles;
2190
2191         return 0;
2192
2193 outprofiles:
2194         device_remove_file(&pd->dev, &th_handle->profiles_attr);
2195 outkzalloc:
2196         kfree(th_handle);
2197         th_handle = NULL;
2198         return ret;
2199 }
2200
2201 static void sony_nc_thermal_cleanup(struct platform_device *pd)
2202 {
2203         if (th_handle) {
2204                 device_remove_file(&pd->dev, &th_handle->profiles_attr);
2205                 device_remove_file(&pd->dev, &th_handle->mode_attr);
2206                 kfree(th_handle);
2207                 th_handle = NULL;
2208         }
2209 }
2210
2211 static void sony_nc_thermal_resume(void)
2212 {
2213         unsigned int status = sony_nc_thermal_mode_get();
2214
2215         if (status != th_handle->mode)
2216                 sony_nc_thermal_mode_set(th_handle->mode);
2217 }
2218
2219 /* resume on LID open */
2220 struct snc_lid_resume_control {
2221         struct device_attribute attrs[3];
2222         unsigned int status;
2223 };
2224 static struct snc_lid_resume_control *lid_ctl;
2225
2226 static ssize_t sony_nc_lid_resume_store(struct device *dev,
2227                                         struct device_attribute *attr,
2228                                         const char *buffer, size_t count)
2229 {
2230         unsigned int result, pos;
2231         unsigned long value;
2232         if (count > 31)
2233                 return -EINVAL;
2234
2235         if (kstrtoul(buffer, 10, &value) || value > 1)
2236                 return -EINVAL;
2237
2238         /* the value we have to write to SNC is a bitmask:
2239          * +--------------+
2240          * | S3 | S4 | S5 |
2241          * +--------------+
2242          *   2    1    0
2243          */
2244         if (strcmp(attr->attr.name, "lid_resume_S3") == 0)
2245                 pos = 2;
2246         else if (strcmp(attr->attr.name, "lid_resume_S4") == 0)
2247                 pos = 1;
2248         else if (strcmp(attr->attr.name, "lid_resume_S5") == 0)
2249                 pos = 0;
2250         else
2251                return -EINVAL;
2252
2253         if (value)
2254                 value = lid_ctl->status | (1 << pos);
2255         else
2256                 value = lid_ctl->status & ~(1 << pos);
2257
2258         if (sony_call_snc_handle(0x0119, value << 0x10 | 0x0100, &result))
2259                 return -EIO;
2260
2261         lid_ctl->status = value;
2262
2263         return count;
2264 }
2265
2266 static ssize_t sony_nc_lid_resume_show(struct device *dev,
2267                                        struct device_attribute *attr, char *buffer)
2268 {
2269         unsigned int pos;
2270
2271         if (strcmp(attr->attr.name, "lid_resume_S3") == 0)
2272                 pos = 2;
2273         else if (strcmp(attr->attr.name, "lid_resume_S4") == 0)
2274                 pos = 1;
2275         else if (strcmp(attr->attr.name, "lid_resume_S5") == 0)
2276                 pos = 0;
2277         else
2278                 return -EINVAL;
2279                
2280         return snprintf(buffer, PAGE_SIZE, "%d\n",
2281                         (lid_ctl->status >> pos) & 0x01);
2282 }
2283
2284 static int sony_nc_lid_resume_setup(struct platform_device *pd)
2285 {
2286         unsigned int result;
2287         int i;
2288
2289         if (sony_call_snc_handle(0x0119, 0x0000, &result))
2290                 return -EIO;
2291
2292         lid_ctl = kzalloc(sizeof(struct snc_lid_resume_control), GFP_KERNEL);
2293         if (!lid_ctl)
2294                 return -ENOMEM;
2295
2296         lid_ctl->status = result & 0x7;
2297
2298         sysfs_attr_init(&lid_ctl->attrs[0].attr);
2299         lid_ctl->attrs[0].attr.name = "lid_resume_S3";
2300         lid_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR;
2301         lid_ctl->attrs[0].show = sony_nc_lid_resume_show;
2302         lid_ctl->attrs[0].store = sony_nc_lid_resume_store;
2303
2304         sysfs_attr_init(&lid_ctl->attrs[1].attr);
2305         lid_ctl->attrs[1].attr.name = "lid_resume_S4";
2306         lid_ctl->attrs[1].attr.mode = S_IRUGO | S_IWUSR;
2307         lid_ctl->attrs[1].show = sony_nc_lid_resume_show;
2308         lid_ctl->attrs[1].store = sony_nc_lid_resume_store;
2309
2310         sysfs_attr_init(&lid_ctl->attrs[2].attr);
2311         lid_ctl->attrs[2].attr.name = "lid_resume_S5";
2312         lid_ctl->attrs[2].attr.mode = S_IRUGO | S_IWUSR;
2313         lid_ctl->attrs[2].show = sony_nc_lid_resume_show;
2314         lid_ctl->attrs[2].store = sony_nc_lid_resume_store;
2315
2316         for (i = 0; i < 3; i++) {
2317                 result = device_create_file(&pd->dev, &lid_ctl->attrs[i]);
2318                 if (result)
2319                         goto liderror;
2320         }
2321
2322         return 0;
2323
2324 liderror:
2325         for (; i > 0; i--)
2326                 device_remove_file(&pd->dev, &lid_ctl->attrs[i]);
2327
2328         kfree(lid_ctl);
2329         lid_ctl = NULL;
2330
2331         return result;
2332 }
2333
2334 static void sony_nc_lid_resume_cleanup(struct platform_device *pd)
2335 {
2336         int i;
2337
2338         if (lid_ctl) {
2339                 for (i = 0; i < 3; i++)
2340                         device_remove_file(&pd->dev, &lid_ctl->attrs[i]);
2341
2342                 kfree(lid_ctl);
2343                 lid_ctl = NULL;
2344         }
2345 }
2346
2347 /* High speed charging function */
2348 static struct device_attribute *hsc_handle;
2349
2350 static ssize_t sony_nc_highspeed_charging_store(struct device *dev,
2351                 struct device_attribute *attr,
2352                 const char *buffer, size_t count)
2353 {
2354         unsigned int result;
2355         unsigned long value;
2356
2357         if (count > 31)
2358                 return -EINVAL;
2359
2360         if (kstrtoul(buffer, 10, &value) || value > 1)
2361                 return -EINVAL;
2362
2363         if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result))
2364                 return -EIO;
2365
2366         return count;
2367 }
2368
2369 static ssize_t sony_nc_highspeed_charging_show(struct device *dev,
2370                 struct device_attribute *attr, char *buffer)
2371 {
2372         unsigned int result;
2373
2374         if (sony_call_snc_handle(0x0131, 0x0100, &result))
2375                 return -EIO;
2376
2377         return snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01);
2378 }
2379
2380 static int sony_nc_highspeed_charging_setup(struct platform_device *pd)
2381 {
2382         unsigned int result;
2383
2384         if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) {
2385                 /* some models advertise the handle but have no implementation
2386                  * for it
2387                  */
2388                 pr_info("No High Speed Charging capability found\n");
2389                 return 0;
2390         }
2391
2392         hsc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2393         if (!hsc_handle)
2394                 return -ENOMEM;
2395
2396         sysfs_attr_init(&hsc_handle->attr);
2397         hsc_handle->attr.name = "battery_highspeed_charging";
2398         hsc_handle->attr.mode = S_IRUGO | S_IWUSR;
2399         hsc_handle->show = sony_nc_highspeed_charging_show;
2400         hsc_handle->store = sony_nc_highspeed_charging_store;
2401
2402         result = device_create_file(&pd->dev, hsc_handle);
2403         if (result) {
2404                 kfree(hsc_handle);
2405                 hsc_handle = NULL;
2406                 return result;
2407         }
2408
2409         return 0;
2410 }
2411
2412 static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd)
2413 {
2414         if (hsc_handle) {
2415                 device_remove_file(&pd->dev, hsc_handle);
2416                 kfree(hsc_handle);
2417                 hsc_handle = NULL;
2418         }
2419 }
2420
2421 /* Touchpad enable/disable */
2422 struct touchpad_control {
2423         struct device_attribute attr;
2424         int handle;
2425 };
2426 static struct touchpad_control *tp_ctl;
2427
2428 static ssize_t sony_nc_touchpad_store(struct device *dev,
2429                 struct device_attribute *attr, const char *buffer, size_t count)
2430 {
2431         unsigned int result;
2432         unsigned long value;
2433
2434         if (count > 31)
2435                 return -EINVAL;
2436
2437         if (kstrtoul(buffer, 10, &value) || value > 1)
2438                 return -EINVAL;
2439
2440         /* sysfs: 0 disabled, 1 enabled
2441          * EC: 0 enabled, 1 disabled
2442          */
2443         if (sony_call_snc_handle(tp_ctl->handle,
2444                                 (!value << 0x10) | 0x100, &result))
2445                 return -EIO;
2446
2447         return count;
2448 }
2449
2450 static ssize_t sony_nc_touchpad_show(struct device *dev,
2451                 struct device_attribute *attr, char *buffer)
2452 {
2453         unsigned int result;
2454
2455         if (sony_call_snc_handle(tp_ctl->handle, 0x000, &result))
2456                 return -EINVAL;
2457
2458         return snprintf(buffer, PAGE_SIZE, "%d\n", !(result & 0x01));
2459 }
2460
2461 static int sony_nc_touchpad_setup(struct platform_device *pd,
2462                 unsigned int handle)
2463 {
2464         int ret = 0;
2465
2466         tp_ctl = kzalloc(sizeof(struct touchpad_control), GFP_KERNEL);
2467         if (!tp_ctl)
2468                 return -ENOMEM;
2469
2470         tp_ctl->handle = handle;
2471
2472         sysfs_attr_init(&tp_ctl->attr.attr);
2473         tp_ctl->attr.attr.name = "touchpad";
2474         tp_ctl->attr.attr.mode = S_IRUGO | S_IWUSR;
2475         tp_ctl->attr.show = sony_nc_touchpad_show;
2476         tp_ctl->attr.store = sony_nc_touchpad_store;
2477
2478         ret = device_create_file(&pd->dev, &tp_ctl->attr);
2479         if (ret) {
2480                 kfree(tp_ctl);
2481                 tp_ctl = NULL;
2482         }
2483
2484         return ret;
2485 }
2486
2487 static void sony_nc_touchpad_cleanup(struct platform_device *pd)
2488 {
2489         if (tp_ctl) {
2490                 device_remove_file(&pd->dev, &tp_ctl->attr);
2491                 kfree(tp_ctl);
2492                 tp_ctl = NULL;
2493         }
2494 }
2495
2496 static void sony_nc_backlight_ng_read_limits(int handle,
2497                 struct sony_backlight_props *props)
2498 {
2499         u64 offset;
2500         int i;
2501         int lvl_table_len = 0;
2502         u8 min = 0xff, max = 0x00;
2503         unsigned char buffer[32] = { 0 };
2504
2505         props->handle = handle;
2506         props->offset = 0;
2507         props->maxlvl = 0xff;
2508
2509         offset = sony_find_snc_handle(handle);
2510
2511         /* try to read the boundaries from ACPI tables, if we fail the above
2512          * defaults should be reasonable
2513          */
2514         i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer,
2515                         32);
2516         if (i < 0)
2517                 return;
2518
2519         switch (handle) {
2520         case 0x012f:
2521         case 0x0137:
2522                 lvl_table_len = 9;
2523                 break;
2524         case 0x143:
2525                 lvl_table_len = 16;
2526                 break;
2527         }
2528
2529         /* the buffer lists brightness levels available, brightness levels are
2530          * from position 0 to 8 in the array, other values are used by ALS
2531          * control.
2532          */
2533         for (i = 0; i < lvl_table_len && i < ARRAY_SIZE(buffer); i++) {
2534
2535                 dprintk("Brightness level: %d\n", buffer[i]);
2536
2537                 if (!buffer[i])
2538                         break;
2539
2540                 if (buffer[i] > max)
2541                         max = buffer[i];
2542                 if (buffer[i] < min)
2543                         min = buffer[i];
2544         }
2545         props->offset = min;
2546         props->maxlvl = max;
2547         dprintk("Brightness levels: min=%d max=%d\n", props->offset,
2548                         props->maxlvl);
2549 }
2550
2551 static void sony_nc_backlight_setup(void)
2552 {
2553         acpi_handle unused;
2554         int max_brightness = 0;
2555         const struct backlight_ops *ops = NULL;
2556         struct backlight_properties props;
2557
2558         if (sony_find_snc_handle(0x12f) >= 0) {
2559                 ops = &sony_backlight_ng_ops;
2560                 sony_bl_props.cmd_base = 0x0100;
2561                 sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
2562                 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
2563
2564         } else if (sony_find_snc_handle(0x137) >= 0) {
2565                 ops = &sony_backlight_ng_ops;
2566                 sony_bl_props.cmd_base = 0x0100;
2567                 sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
2568                 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
2569
2570         } else if (sony_find_snc_handle(0x143) >= 0) {
2571                 ops = &sony_backlight_ng_ops;
2572                 sony_bl_props.cmd_base = 0x3000;
2573                 sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props);
2574                 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
2575
2576         } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
2577                                                 &unused))) {
2578                 ops = &sony_backlight_ops;
2579                 max_brightness = SONY_MAX_BRIGHTNESS - 1;
2580
2581         } else
2582                 return;
2583
2584         memset(&props, 0, sizeof(struct backlight_properties));
2585         props.type = BACKLIGHT_PLATFORM;
2586         props.max_brightness = max_brightness;
2587         sony_bl_props.dev = backlight_device_register("sony", NULL,
2588                                                       &sony_bl_props,
2589                                                       ops, &props);
2590
2591         if (IS_ERR(sony_bl_props.dev)) {
2592                 pr_warn("unable to register backlight device\n");
2593                 sony_bl_props.dev = NULL;
2594         } else
2595                 sony_bl_props.dev->props.brightness =
2596                         ops->get_brightness(sony_bl_props.dev);
2597 }
2598
2599 static void sony_nc_backlight_cleanup(void)
2600 {
2601         if (sony_bl_props.dev)
2602                 backlight_device_unregister(sony_bl_props.dev);
2603 }
2604
2605 static int sony_nc_add(struct acpi_device *device)
2606 {
2607         acpi_status status;
2608         int result = 0;
2609         acpi_handle handle;
2610         struct sony_nc_value *item;
2611
2612         pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
2613
2614         sony_nc_acpi_device = device;
2615         strcpy(acpi_device_class(device), "sony/hotkey");
2616
2617         sony_nc_acpi_handle = device->handle;
2618
2619         /* read device status */
2620         result = acpi_bus_get_status(device);
2621         /* bail IFF the above call was successful and the device is not present */
2622         if (!result && !device->status.present) {
2623                 dprintk("Device not present\n");
2624                 result = -ENODEV;
2625                 goto outwalk;
2626         }
2627
2628         result = sony_pf_add();
2629         if (result)
2630                 goto outpresent;
2631
2632         if (debug) {
2633                 status = acpi_walk_namespace(ACPI_TYPE_METHOD,
2634                                 sony_nc_acpi_handle, 1, sony_walk_callback,
2635                                 NULL, NULL, NULL);
2636                 if (ACPI_FAILURE(status)) {
2637                         pr_warn("unable to walk acpi resources\n");
2638                         result = -ENODEV;
2639                         goto outpresent;
2640                 }
2641         }
2642
2643         result = sony_laptop_setup_input(device);
2644         if (result) {
2645                 pr_err("Unable to create input devices\n");
2646                 goto outplatform;
2647         }
2648
2649         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
2650                                          &handle))) {
2651                 int arg = 1;
2652                 if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
2653                         dprintk("ECON Method failed\n");
2654         }
2655
2656         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
2657                                          &handle))) {
2658                 dprintk("Doing SNC setup\n");
2659                 /* retrieve the available handles */
2660                 result = sony_nc_handles_setup(sony_pf_device);
2661                 if (!result)
2662                         sony_nc_function_setup(device, sony_pf_device);
2663         }
2664
2665         /* setup input devices and helper fifo */
2666         if (acpi_video_backlight_support()) {
2667                 pr_info("brightness ignored, must be controlled by ACPI video driver\n");
2668         } else {
2669                 sony_nc_backlight_setup();
2670         }
2671
2672         /* create sony_pf sysfs attributes related to the SNC device */
2673         for (item = sony_nc_values; item->name; ++item) {
2674
2675                 if (!debug && item->debug)
2676                         continue;
2677
2678                 /* find the available acpiget as described in the DSDT */
2679                 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
2680                         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
2681                                                          *item->acpiget,
2682                                                          &handle))) {
2683                                 dprintk("Found %s getter: %s\n",
2684                                                 item->name, *item->acpiget);
2685                                 item->devattr.attr.mode |= S_IRUGO;
2686                                 break;
2687                         }
2688                 }
2689
2690                 /* find the available acpiset as described in the DSDT */
2691                 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
2692                         if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
2693                                                          *item->acpiset,
2694                                                          &handle))) {
2695                                 dprintk("Found %s setter: %s\n",
2696                                                 item->name, *item->acpiset);
2697                                 item->devattr.attr.mode |= S_IWUSR;
2698                                 break;
2699                         }
2700                 }
2701
2702                 if (item->devattr.attr.mode != 0) {
2703                         result =
2704                             device_create_file(&sony_pf_device->dev,
2705                                                &item->devattr);
2706                         if (result)
2707                                 goto out_sysfs;
2708                 }
2709         }
2710
2711         return 0;
2712
2713 out_sysfs:
2714         for (item = sony_nc_values; item->name; ++item) {
2715                 device_remove_file(&sony_pf_device->dev, &item->devattr);
2716         }
2717         sony_nc_backlight_cleanup();
2718         sony_nc_function_cleanup(sony_pf_device);
2719         sony_nc_handles_cleanup(sony_pf_device);
2720
2721 outplatform:
2722         sony_laptop_remove_input();
2723
2724 outpresent:
2725         sony_pf_remove();
2726
2727 outwalk:
2728         sony_nc_rfkill_cleanup();
2729         return result;
2730 }
2731
2732 static int sony_nc_remove(struct acpi_device *device, int type)
2733 {
2734         struct sony_nc_value *item;
2735
2736         sony_nc_backlight_cleanup();
2737
2738         sony_nc_acpi_device = NULL;
2739
2740         for (item = sony_nc_values; item->name; ++item) {
2741                 device_remove_file(&sony_pf_device->dev, &item->devattr);
2742         }
2743
2744         sony_nc_function_cleanup(sony_pf_device);
2745         sony_nc_handles_cleanup(sony_pf_device);
2746         sony_pf_remove();
2747         sony_laptop_remove_input();
2748         dprintk(SONY_NC_DRIVER_NAME " removed.\n");
2749
2750         return 0;
2751 }
2752
2753 static const struct acpi_device_id sony_device_ids[] = {
2754         {SONY_NC_HID, 0},
2755         {SONY_PIC_HID, 0},
2756         {"", 0},
2757 };
2758 MODULE_DEVICE_TABLE(acpi, sony_device_ids);
2759
2760 static const struct acpi_device_id sony_nc_device_ids[] = {
2761         {SONY_NC_HID, 0},
2762         {"", 0},
2763 };
2764
2765 static struct acpi_driver sony_nc_driver = {
2766         .name = SONY_NC_DRIVER_NAME,
2767         .class = SONY_NC_CLASS,
2768         .ids = sony_nc_device_ids,
2769         .owner = THIS_MODULE,
2770         .ops = {
2771                 .add = sony_nc_add,
2772                 .remove = sony_nc_remove,
2773                 .resume = sony_nc_resume,
2774                 .notify = sony_nc_notify,
2775                 },
2776 };
2777
2778 /*********** SPIC (SNY6001) Device ***********/
2779
2780 #define SONYPI_DEVICE_TYPE1     0x00000001
2781 #define SONYPI_DEVICE_TYPE2     0x00000002
2782 #define SONYPI_DEVICE_TYPE3     0x00000004
2783
2784 #define SONYPI_TYPE1_OFFSET     0x04
2785 #define SONYPI_TYPE2_OFFSET     0x12
2786 #define SONYPI_TYPE3_OFFSET     0x12
2787
2788 struct sony_pic_ioport {
2789         struct acpi_resource_io io1;
2790         struct acpi_resource_io io2;
2791         struct list_head        list;
2792 };
2793
2794 struct sony_pic_irq {
2795         struct acpi_resource_irq        irq;
2796         struct list_head                list;
2797 };
2798
2799 struct sonypi_eventtypes {
2800         u8                      data;
2801         unsigned long           mask;
2802         struct sonypi_event     *events;
2803 };
2804
2805 struct sony_pic_dev {
2806         struct acpi_device              *acpi_dev;
2807         struct sony_pic_irq             *cur_irq;
2808         struct sony_pic_ioport          *cur_ioport;
2809         struct list_head                interrupts;
2810         struct list_head                ioports;
2811         struct mutex                    lock;
2812         struct sonypi_eventtypes        *event_types;
2813         int                             (*handle_irq)(const u8, const u8);
2814         int                             model;
2815         u16                             evport_offset;
2816         u8                              camera_power;
2817         u8                              bluetooth_power;
2818         u8                              wwan_power;
2819 };
2820
2821 static struct sony_pic_dev spic_dev = {
2822         .interrupts     = LIST_HEAD_INIT(spic_dev.interrupts),
2823         .ioports        = LIST_HEAD_INIT(spic_dev.ioports),
2824 };
2825
2826 static int spic_drv_registered;
2827
2828 /* Event masks */
2829 #define SONYPI_JOGGER_MASK                      0x00000001
2830 #define SONYPI_CAPTURE_MASK                     0x00000002
2831 #define SONYPI_FNKEY_MASK                       0x00000004
2832 #define SONYPI_BLUETOOTH_MASK                   0x00000008
2833 #define SONYPI_PKEY_MASK                        0x00000010
2834 #define SONYPI_BACK_MASK                        0x00000020
2835 #define SONYPI_HELP_MASK                        0x00000040
2836 #define SONYPI_LID_MASK                         0x00000080
2837 #define SONYPI_ZOOM_MASK                        0x00000100
2838 #define SONYPI_THUMBPHRASE_MASK                 0x00000200
2839 #define SONYPI_MEYE_MASK                        0x00000400
2840 #define SONYPI_MEMORYSTICK_MASK                 0x00000800
2841 #define SONYPI_BATTERY_MASK                     0x00001000
2842 #define SONYPI_WIRELESS_MASK                    0x00002000
2843
2844 struct sonypi_event {
2845         u8      data;
2846         u8      event;
2847 };
2848
2849 /* The set of possible button release events */
2850 static struct sonypi_event sonypi_releaseev[] = {
2851         { 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED },
2852         { 0, 0 }
2853 };
2854
2855 /* The set of possible jogger events  */
2856 static struct sonypi_event sonypi_joggerev[] = {
2857         { 0x1f, SONYPI_EVENT_JOGDIAL_UP },
2858         { 0x01, SONYPI_EVENT_JOGDIAL_DOWN },
2859         { 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED },
2860         { 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED },
2861         { 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP },
2862         { 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN },
2863         { 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED },
2864         { 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED },
2865         { 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP },
2866         { 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN },
2867         { 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED },
2868         { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED },
2869         { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED },
2870         { 0, 0 }
2871 };
2872
2873 /* The set of possible capture button events */
2874 static struct sonypi_event sonypi_captureev[] = {
2875         { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
2876         { 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
2877         { 0x40, SONYPI_EVENT_CAPTURE_PRESSED },
2878         { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
2879         { 0, 0 }
2880 };
2881
2882 /* The set of possible fnkeys events */
2883 static struct sonypi_event sonypi_fnkeyev[] = {
2884         { 0x10, SONYPI_EVENT_FNKEY_ESC },
2885         { 0x11, SONYPI_EVENT_FNKEY_F1 },
2886         { 0x12, SONYPI_EVENT_FNKEY_F2 },
2887         { 0x13, SONYPI_EVENT_FNKEY_F3 },
2888         { 0x14, SONYPI_EVENT_FNKEY_F4 },
2889         { 0x15, SONYPI_EVENT_FNKEY_F5 },
2890         { 0x16, SONYPI_EVENT_FNKEY_F6 },
2891         { 0x17, SONYPI_EVENT_FNKEY_F7 },
2892         { 0x18, SONYPI_EVENT_FNKEY_F8 },
2893         { 0x19, SONYPI_EVENT_FNKEY_F9 },
2894         { 0x1a, SONYPI_EVENT_FNKEY_F10 },
2895         { 0x1b, SONYPI_EVENT_FNKEY_F11 },
2896         { 0x1c, SONYPI_EVENT_FNKEY_F12 },
2897         { 0x1f, SONYPI_EVENT_FNKEY_RELEASED },
2898         { 0x21, SONYPI_EVENT_FNKEY_1 },
2899         { 0x22, SONYPI_EVENT_FNKEY_2 },
2900         { 0x31, SONYPI_EVENT_FNKEY_D },
2901         { 0x32, SONYPI_EVENT_FNKEY_E },
2902         { 0x33, SONYPI_EVENT_FNKEY_F },
2903         { 0x34, SONYPI_EVENT_FNKEY_S },
2904         { 0x35, SONYPI_EVENT_FNKEY_B },
2905         { 0x36, SONYPI_EVENT_FNKEY_ONLY },
2906         { 0, 0 }
2907 };
2908
2909 /* The set of possible program key events */
2910 static struct sonypi_event sonypi_pkeyev[] = {
2911         { 0x01, SONYPI_EVENT_PKEY_P1 },
2912         { 0x02, SONYPI_EVENT_PKEY_P2 },
2913         { 0x04, SONYPI_EVENT_PKEY_P3 },
2914         { 0x20, SONYPI_EVENT_PKEY_P1 },
2915         { 0, 0 }
2916 };
2917
2918 /* The set of possible bluetooth events */
2919 static struct sonypi_event sonypi_blueev[] = {
2920         { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
2921         { 0x59, SONYPI_EVENT_BLUETOOTH_ON },
2922         { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
2923         { 0, 0 }
2924 };
2925
2926 /* The set of possible wireless events */
2927 static struct sonypi_event sonypi_wlessev[] = {
2928         { 0x59, SONYPI_EVENT_IGNORE },
2929         { 0x5a, SONYPI_EVENT_IGNORE },
2930         { 0, 0 }
2931 };
2932
2933 /* The set of possible back button events */
2934 static struct sonypi_event sonypi_backev[] = {
2935         { 0x20, SONYPI_EVENT_BACK_PRESSED },
2936         { 0, 0 }
2937 };
2938
2939 /* The set of possible help button events */
2940 static struct sonypi_event sonypi_helpev[] = {
2941         { 0x3b, SONYPI_EVENT_HELP_PRESSED },
2942         { 0, 0 }
2943 };
2944
2945
2946 /* The set of possible lid events */
2947 static struct sonypi_event sonypi_lidev[] = {
2948         { 0x51, SONYPI_EVENT_LID_CLOSED },
2949         { 0x50, SONYPI_EVENT_LID_OPENED },
2950         { 0, 0 }
2951 };
2952
2953 /* The set of possible zoom events */
2954 static struct sonypi_event sonypi_zoomev[] = {
2955         { 0x39, SONYPI_EVENT_ZOOM_PRESSED },
2956         { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED },
2957         { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED },
2958         { 0x04, SONYPI_EVENT_ZOOM_PRESSED },
2959         { 0, 0 }
2960 };
2961
2962 /* The set of possible thumbphrase events */
2963 static struct sonypi_event sonypi_thumbphraseev[] = {
2964         { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED },
2965         { 0, 0 }
2966 };
2967
2968 /* The set of possible motioneye camera events */
2969 static struct sonypi_event sonypi_meyeev[] = {
2970         { 0x00, SONYPI_EVENT_MEYE_FACE },
2971         { 0x01, SONYPI_EVENT_MEYE_OPPOSITE },
2972         { 0, 0 }
2973 };
2974
2975 /* The set of possible memorystick events */
2976 static struct sonypi_event sonypi_memorystickev[] = {
2977         { 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT },
2978         { 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT },
2979         { 0, 0 }
2980 };
2981
2982 /* The set of possible battery events */
2983 static struct sonypi_event sonypi_batteryev[] = {
2984         { 0x20, SONYPI_EVENT_BATTERY_INSERT },
2985         { 0x30, SONYPI_EVENT_BATTERY_REMOVE },
2986         { 0, 0 }
2987 };
2988
2989 /* The set of possible volume events */
2990 static struct sonypi_event sonypi_volumeev[] = {
2991         { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED },
2992         { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED },
2993         { 0, 0 }
2994 };
2995
2996 /* The set of possible brightness events */
2997 static struct sonypi_event sonypi_brightnessev[] = {
2998         { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED },
2999         { 0, 0 }
3000 };
3001
3002 static struct sonypi_eventtypes type1_events[] = {
3003         { 0, 0xffffffff, sonypi_releaseev },
3004         { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
3005         { 0x30, SONYPI_LID_MASK, sonypi_lidev },
3006         { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
3007         { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
3008         { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3009         { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
3010         { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
3011         { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3012         { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
3013         { 0 },
3014 };
3015 static struct sonypi_eventtypes type2_events[] = {
3016         { 0, 0xffffffff, sonypi_releaseev },
3017         { 0x38, SONYPI_LID_MASK, sonypi_lidev },
3018         { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
3019         { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
3020         { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3021         { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
3022         { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
3023         { 0x11, SONYPI_BACK_MASK, sonypi_backev },
3024         { 0x21, SONYPI_HELP_MASK, sonypi_helpev },
3025         { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
3026         { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
3027         { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3028         { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
3029         { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
3030         { 0 },
3031 };
3032 static struct sonypi_eventtypes type3_events[] = {
3033         { 0, 0xffffffff, sonypi_releaseev },
3034         { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3035         { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
3036         { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3037         { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
3038         { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
3039         { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev },
3040         { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev },
3041         { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev },
3042         { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev },
3043         { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev },
3044         { 0 },
3045 };
3046
3047 /* low level spic calls */
3048 #define ITERATIONS_LONG         10000
3049 #define ITERATIONS_SHORT        10
3050 #define wait_on_command(command, iterations) {                          \
3051         unsigned int n = iterations;                                    \
3052         while (--n && (command))                                        \
3053                 udelay(1);                                              \
3054         if (!n)                                                         \
3055                 dprintk("command failed at %s : %s (line %d)\n",        \
3056                                 __FILE__, __func__, __LINE__);  \
3057 }
3058
3059 static u8 sony_pic_call1(u8 dev)
3060 {
3061         u8 v1, v2;
3062
3063         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3064                         ITERATIONS_LONG);
3065         outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3066         v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
3067         v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
3068         dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1);
3069         return v2;
3070 }
3071
3072 static u8 sony_pic_call2(u8 dev, u8 fn)
3073 {
3074         u8 v1;
3075
3076         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3077                         ITERATIONS_LONG);
3078         outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3079         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3080                         ITERATIONS_LONG);
3081         outb(fn, spic_dev.cur_ioport->io1.minimum);
3082         v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
3083         dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1);
3084         return v1;
3085 }
3086
3087 static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
3088 {
3089         u8 v1;
3090
3091         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3092         outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3093         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3094         outb(fn, spic_dev.cur_ioport->io1.minimum);
3095         wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3096         outb(v, spic_dev.cur_ioport->io1.minimum);
3097         v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
3098         dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
3099                         dev, fn, v, v1);
3100         return v1;
3101 }
3102
3103 /*
3104  * minidrivers for SPIC models
3105  */
3106 static int type3_handle_irq(const u8 data_mask, const u8 ev)
3107 {
3108         /*
3109          * 0x31 could mean we have to take some extra action and wait for
3110          * the next irq for some Type3 models, it will generate a new
3111          * irq and we can read new data from the device:
3112          *  - 0x5c and 0x5f requires 0xA0
3113          *  - 0x61 requires 0xB3
3114          */
3115         if (data_mask == 0x31) {
3116                 if (ev == 0x5c || ev == 0x5f)
3117                         sony_pic_call1(0xA0);
3118                 else if (ev == 0x61)
3119                         sony_pic_call1(0xB3);
3120                 return 0;
3121         }
3122         return 1;
3123 }
3124
3125 static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
3126 {
3127         struct pci_dev *pcidev;
3128
3129         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3130                         PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
3131         if (pcidev) {
3132                 dev->model = SONYPI_DEVICE_TYPE1;
3133                 dev->evport_offset = SONYPI_TYPE1_OFFSET;
3134                 dev->event_types = type1_events;
3135                 goto out;
3136         }
3137
3138         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3139                         PCI_DEVICE_ID_INTEL_ICH6_1, NULL);
3140         if (pcidev) {
3141                 dev->model = SONYPI_DEVICE_TYPE2;
3142                 dev->evport_offset = SONYPI_TYPE2_OFFSET;
3143                 dev->event_types = type2_events;
3144                 goto out;
3145         }
3146
3147         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3148                         PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
3149         if (pcidev) {
3150                 dev->model = SONYPI_DEVICE_TYPE3;
3151                 dev->handle_irq = type3_handle_irq;
3152                 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3153                 dev->event_types = type3_events;
3154                 goto out;
3155         }
3156
3157         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3158                         PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
3159         if (pcidev) {
3160                 dev->model = SONYPI_DEVICE_TYPE3;
3161                 dev->handle_irq = type3_handle_irq;
3162                 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3163                 dev->event_types = type3_events;
3164                 goto out;
3165         }
3166
3167         pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3168                         PCI_DEVICE_ID_INTEL_ICH9_1, NULL);
3169         if (pcidev) {
3170                 dev->model = SONYPI_DEVICE_TYPE3;
3171                 dev->handle_irq = type3_handle_irq;
3172                 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3173                 dev->event_types = type3_events;
3174                 goto out;
3175         }
3176
3177         /* default */
3178         dev->model = SONYPI_DEVICE_TYPE2;
3179         dev->evport_offset = SONYPI_TYPE2_OFFSET;
3180         dev->event_types = type2_events;
3181
3182 out:
3183         if (pcidev)
3184                 pci_dev_put(pcidev);
3185
3186         pr_info("detected Type%d model\n",
3187                 dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
3188                 dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
3189 }
3190
3191 /* camera tests and poweron/poweroff */
3192 #define SONYPI_CAMERA_PICTURE           5
3193 #define SONYPI_CAMERA_CONTROL           0x10
3194
3195 #define SONYPI_CAMERA_BRIGHTNESS                0
3196 #define SONYPI_CAMERA_CONTRAST                  1
3197 #define SONYPI_CAMERA_HUE                       2
3198 #define SONYPI_CAMERA_COLOR                     3
3199 #define SONYPI_CAMERA_SHARPNESS                 4
3200
3201 #define SONYPI_CAMERA_EXPOSURE_MASK             0xC
3202 #define SONYPI_CAMERA_WHITE_BALANCE_MASK        0x3
3203 #define SONYPI_CAMERA_PICTURE_MODE_MASK         0x30
3204 #define SONYPI_CAMERA_MUTE_MASK                 0x40
3205
3206 /* the rest don't need a loop until not 0xff */
3207 #define SONYPI_CAMERA_AGC                       6
3208 #define SONYPI_CAMERA_AGC_MASK                  0x30
3209 #define SONYPI_CAMERA_SHUTTER_MASK              0x7
3210
3211 #define SONYPI_CAMERA_SHUTDOWN_REQUEST          7
3212 #define SONYPI_CAMERA_CONTROL                   0x10
3213
3214 #define SONYPI_CAMERA_STATUS                    7
3215 #define SONYPI_CAMERA_STATUS_READY              0x2
3216 #define SONYPI_CAMERA_STATUS_POSITION           0x4
3217
3218 #define SONYPI_DIRECTION_BACKWARDS              0x4
3219
3220 #define SONYPI_CAMERA_REVISION                  8
3221 #define SONYPI_CAMERA_ROMVERSION                9
3222
3223 static int __sony_pic_camera_ready(void)
3224 {
3225         u8 v;
3226
3227         v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
3228         return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
3229 }
3230
3231 static int __sony_pic_camera_off(void)
3232 {
3233         if (!camera) {
3234                 pr_warn("camera control not enabled\n");
3235                 return -ENODEV;
3236         }
3237
3238         wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
3239                                 SONYPI_CAMERA_MUTE_MASK),
3240                         ITERATIONS_SHORT);
3241
3242         if (spic_dev.camera_power) {
3243                 sony_pic_call2(0x91, 0);
3244                 spic_dev.camera_power = 0;
3245         }
3246         return 0;
3247 }
3248
3249 static int __sony_pic_camera_on(void)
3250 {
3251         int i, j, x;
3252
3253         if (!camera) {
3254                 pr_warn("camera control not enabled\n");
3255                 return -ENODEV;
3256         }
3257
3258         if (spic_dev.camera_power)
3259                 return 0;
3260
3261         for (j = 5; j > 0; j--) {
3262
3263                 for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
3264                         msleep(10);
3265                 sony_pic_call1(0x93);
3266
3267                 for (i = 400; i > 0; i--) {
3268                         if (__sony_pic_camera_ready())
3269                                 break;
3270                         msleep(10);
3271                 }
3272                 if (i)
3273                         break;
3274         }
3275
3276         if (j == 0) {
3277                 pr_warn("failed to power on camera\n");
3278                 return -ENODEV;
3279         }
3280
3281         wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL,
3282                                 0x5a),
3283                         ITERATIONS_SHORT);
3284
3285         spic_dev.camera_power = 1;
3286         return 0;
3287 }
3288
3289 /* External camera command (exported to the motion eye v4l driver) */
3290 int sony_pic_camera_command(int command, u8 value)
3291 {
3292         if (!camera)
3293                 return -EIO;
3294
3295         mutex_lock(&spic_dev.lock);
3296
3297         switch (command) {
3298         case SONY_PIC_COMMAND_SETCAMERA:
3299                 if (value)
3300                         __sony_pic_camera_on();
3301                 else
3302                         __sony_pic_camera_off();
3303                 break;
3304         case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
3305                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value),
3306                                 ITERATIONS_SHORT);
3307                 break;
3308         case SONY_PIC_COMMAND_SETCAMERACONTRAST:
3309                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
3310                                 ITERATIONS_SHORT);
3311                 break;
3312         case SONY_PIC_COMMAND_SETCAMERAHUE:
3313                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
3314                                 ITERATIONS_SHORT);
3315                 break;
3316         case SONY_PIC_COMMAND_SETCAMERACOLOR:
3317                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
3318                                 ITERATIONS_SHORT);
3319                 break;
3320         case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
3321                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
3322                                 ITERATIONS_SHORT);
3323                 break;
3324         case SONY_PIC_COMMAND_SETCAMERAPICTURE:
3325                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
3326                                 ITERATIONS_SHORT);
3327                 break;
3328         case SONY_PIC_COMMAND_SETCAMERAAGC:
3329                 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
3330                                 ITERATIONS_SHORT);
3331                 break;
3332         default:
3333                 pr_err("sony_pic_camera_command invalid: %d\n", command);
3334                 break;
3335         }
3336         mutex_unlock(&spic_dev.lock);
3337         return 0;
3338 }
3339 EXPORT_SYMBOL(sony_pic_camera_command);
3340
3341 /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */
3342 static void __sony_pic_set_wwanpower(u8 state)
3343 {
3344         state = !!state;
3345         if (spic_dev.wwan_power == state)
3346                 return;
3347         sony_pic_call2(0xB0, state);
3348         sony_pic_call1(0x82);
3349         spic_dev.wwan_power = state;
3350 }
3351
3352 static ssize_t sony_pic_wwanpower_store(struct device *dev,
3353                 struct device_attribute *attr,
3354                 const char *buffer, size_t count)
3355 {
3356         unsigned long value;
3357         if (count > 31)
3358                 return -EINVAL;
3359
3360         if (kstrtoul(buffer, 10, &value))
3361                 return -EINVAL;
3362
3363         mutex_lock(&spic_dev.lock);
3364         __sony_pic_set_wwanpower(value);
3365         mutex_unlock(&spic_dev.lock);
3366
3367         return count;
3368 }
3369
3370 static ssize_t sony_pic_wwanpower_show(struct device *dev,
3371                 struct device_attribute *attr, char *buffer)
3372 {
3373         ssize_t count;
3374         mutex_lock(&spic_dev.lock);
3375         count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.wwan_power);
3376         mutex_unlock(&spic_dev.lock);
3377         return count;
3378 }
3379
3380 /* bluetooth subsystem power state */
3381 static void __sony_pic_set_bluetoothpower(u8 state)
3382 {
3383         state = !!state;
3384         if (spic_dev.bluetooth_power == state)
3385                 return;
3386         sony_pic_call2(0x96, state);
3387         sony_pic_call1(0x82);
3388         spic_dev.bluetooth_power = state;
3389 }
3390
3391 static ssize_t sony_pic_bluetoothpower_store(struct device *dev,
3392                 struct device_attribute *attr,
3393                 const char *buffer, size_t count)
3394 {
3395         unsigned long value;
3396         if (count > 31)
3397                 return -EINVAL;
3398
3399         if (kstrtoul(buffer, 10, &value))
3400                 return -EINVAL;
3401
3402         mutex_lock(&spic_dev.lock);
3403         __sony_pic_set_bluetoothpower(value);
3404         mutex_unlock(&spic_dev.lock);
3405
3406         return count;
3407 }
3408
3409 static ssize_t sony_pic_bluetoothpower_show(struct device *dev,
3410                 struct device_attribute *attr, char *buffer)
3411 {
3412         ssize_t count = 0;
3413         mutex_lock(&spic_dev.lock);
3414         count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power);
3415         mutex_unlock(&spic_dev.lock);
3416         return count;
3417 }
3418
3419 /* fan speed */
3420 /* FAN0 information (reverse engineered from ACPI tables) */
3421 #define SONY_PIC_FAN0_STATUS    0x93
3422 static int sony_pic_set_fanspeed(unsigned long value)
3423 {
3424         return ec_write(SONY_PIC_FAN0_STATUS, value);
3425 }
3426
3427 static int sony_pic_get_fanspeed(u8 *value)
3428 {
3429         return ec_read(SONY_PIC_FAN0_STATUS, value);
3430 }
3431
3432 static ssize_t sony_pic_fanspeed_store(struct device *dev,
3433                 struct device_attribute *attr,
3434                 const char *buffer, size_t count)
3435 {
3436         unsigned long value;
3437         if (count > 31)
3438                 return -EINVAL;
3439
3440         if (kstrtoul(buffer, 10, &value))
3441                 return -EINVAL;
3442
3443         if (sony_pic_set_fanspeed(value))
3444                 return -EIO;
3445
3446         return count;
3447 }
3448
3449 static ssize_t sony_pic_fanspeed_show(struct device *dev,
3450                 struct device_attribute *attr, char *buffer)
3451 {
3452         u8 value = 0;
3453         if (sony_pic_get_fanspeed(&value))
3454                 return -EIO;
3455
3456         return snprintf(buffer, PAGE_SIZE, "%d\n", value);
3457 }
3458
3459 #define SPIC_ATTR(_name, _mode)                                 \
3460 struct device_attribute spic_attr_##_name = __ATTR(_name,       \
3461                 _mode, sony_pic_## _name ##_show,               \
3462                 sony_pic_## _name ##_store)
3463
3464 static SPIC_ATTR(bluetoothpower, 0644);
3465 static SPIC_ATTR(wwanpower, 0644);
3466 static SPIC_ATTR(fanspeed, 0644);
3467
3468 static struct attribute *spic_attributes[] = {
3469         &spic_attr_bluetoothpower.attr,
3470         &spic_attr_wwanpower.attr,
3471         &spic_attr_fanspeed.attr,
3472         NULL
3473 };
3474
3475 static struct attribute_group spic_attribute_group = {
3476         .attrs = spic_attributes
3477 };
3478
3479 /******** SONYPI compatibility **********/
3480 #ifdef CONFIG_SONYPI_COMPAT
3481
3482 /* battery / brightness / temperature  addresses */
3483 #define SONYPI_BAT_FLAGS        0x81
3484 #define SONYPI_LCD_LIGHT        0x96
3485 #define SONYPI_BAT1_PCTRM       0xa0
3486 #define SONYPI_BAT1_LEFT        0xa2
3487 #define SONYPI_BAT1_MAXRT       0xa4
3488 #define SONYPI_BAT2_PCTRM       0xa8
3489 #define SONYPI_BAT2_LEFT        0xaa
3490 #define SONYPI_BAT2_MAXRT       0xac
3491 #define SONYPI_BAT1_MAXTK       0xb0
3492 #define SONYPI_BAT1_FULL        0xb2
3493 #define SONYPI_BAT2_MAXTK       0xb8
3494 #define SONYPI_BAT2_FULL        0xba
3495 #define SONYPI_TEMP_STATUS      0xC1
3496
3497 struct sonypi_compat_s {
3498         struct fasync_struct    *fifo_async;
3499         struct kfifo            fifo;
3500         spinlock_t              fifo_lock;
3501         wait_queue_head_t       fifo_proc_list;
3502         atomic_t                open_count;
3503 };
3504 static struct sonypi_compat_s sonypi_compat = {
3505         .open_count = ATOMIC_INIT(0),
3506 };
3507
3508 static int sonypi_misc_fasync(int fd, struct file *filp, int on)
3509 {
3510         return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
3511 }
3512
3513 static int sonypi_misc_release(struct inode *inode, struct file *file)
3514 {
3515         atomic_dec(&sonypi_compat.open_count);
3516         return 0;
3517 }
3518
3519 static int sonypi_misc_open(struct inode *inode, struct file *file)
3520 {
3521         /* Flush input queue on first open */
3522         unsigned long flags;
3523
3524         spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
3525
3526         if (atomic_inc_return(&sonypi_compat.open_count) == 1)
3527                 kfifo_reset(&sonypi_compat.fifo);
3528
3529         spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
3530
3531         return 0;
3532 }
3533
3534 static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
3535                                 size_t count, loff_t *pos)
3536 {
3537         ssize_t ret;
3538         unsigned char c;
3539
3540         if ((kfifo_len(&sonypi_compat.fifo) == 0) &&
3541             (file->f_flags & O_NONBLOCK))
3542                 return -EAGAIN;
3543
3544         ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
3545                                        kfifo_len(&sonypi_compat.fifo) != 0);
3546         if (ret)
3547                 return ret;
3548
3549         while (ret < count &&
3550                (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c),
3551                           &sonypi_compat.fifo_lock) == sizeof(c))) {
3552                 if (put_user(c, buf++))
3553                         return -EFAULT;
3554                 ret++;
3555         }
3556
3557         if (ret > 0) {
3558                 struct inode *inode = file->f_path.dentry->d_inode;
3559                 inode->i_atime = current_fs_time(inode->i_sb);
3560         }
3561
3562         return ret;
3563 }
3564
3565 static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
3566 {
3567         poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
3568         if (kfifo_len(&sonypi_compat.fifo))
3569                 return POLLIN | POLLRDNORM;
3570         return 0;
3571 }
3572
3573 static int ec_read16(u8 addr, u16 *value)
3574 {
3575         u8 val_lb, val_hb;
3576         if (ec_read(addr, &val_lb))
3577                 return -1;
3578         if (ec_read(addr + 1, &val_hb))
3579                 return -1;
3580         *value = val_lb | (val_hb << 8);
3581         return 0;
3582 }
3583
3584 static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
3585                                                         unsigned long arg)
3586 {
3587         int ret = 0;
3588         void __user *argp = (void __user *)arg;
3589         u8 val8;
3590         u16 val16;
3591         int value;
3592
3593         mutex_lock(&spic_dev.lock);
3594         switch (cmd) {
3595         case SONYPI_IOCGBRT:
3596                 if (sony_bl_props.dev == NULL) {
3597                         ret = -EIO;
3598                         break;
3599                 }
3600                 if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL,
3601                                         &value)) {
3602                         ret = -EIO;
3603                         break;
3604                 }
3605                 val8 = ((value & 0xff) - 1) << 5;
3606                 if (copy_to_user(argp, &val8, sizeof(val8)))
3607                                 ret = -EFAULT;
3608                 break;
3609         case SONYPI_IOCSBRT:
3610                 if (sony_bl_props.dev == NULL) {
3611                         ret = -EIO;
3612                         break;
3613                 }
3614                 if (copy_from_user(&val8, argp, sizeof(val8))) {
3615                         ret = -EFAULT;
3616                         break;
3617                 }
3618                 value = (val8 >> 5) + 1;
3619                 if (sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &value,
3620                                         NULL)) {
3621                         ret = -EIO;
3622                         break;
3623                 }
3624                 /* sync the backlight device status */
3625                 sony_bl_props.dev->props.brightness =
3626                     sony_backlight_get_brightness(sony_bl_props.dev);
3627                 break;
3628         case SONYPI_IOCGBAT1CAP:
3629                 if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
3630                         ret = -EIO;
3631                         break;
3632                 }
3633                 if (copy_to_user(argp, &val16, sizeof(val16)))
3634                         ret = -EFAULT;
3635                 break;
3636         case SONYPI_IOCGBAT1REM:
3637                 if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
3638                         ret = -EIO;
3639                         break;
3640                 }
3641                 if (copy_to_user(argp, &val16, sizeof(val16)))
3642                         ret = -EFAULT;
3643                 break;
3644         case SONYPI_IOCGBAT2CAP:
3645                 if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
3646                         ret = -EIO;
3647                         break;
3648                 }
3649                 if (copy_to_user(argp, &val16, sizeof(val16)))
3650                         ret = -EFAULT;
3651                 break;
3652         case SONYPI_IOCGBAT2REM:
3653                 if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
3654                         ret = -EIO;
3655                         break;
3656                 }
3657                 if (copy_to_user(argp, &val16, sizeof(val16)))
3658                         ret = -EFAULT;
3659                 break;
3660         case SONYPI_IOCGBATFLAGS:
3661                 if (ec_read(SONYPI_BAT_FLAGS, &val8)) {
3662                         ret = -EIO;
3663                         break;
3664                 }
3665                 val8 &= 0x07;
3666                 if (copy_to_user(argp, &val8, sizeof(val8)))
3667                         ret = -EFAULT;
3668                 break;
3669         case SONYPI_IOCGBLUE:
3670                 val8 = spic_dev.bluetooth_power;
3671                 if (copy_to_user(argp, &val8, sizeof(val8)))
3672                         ret = -EFAULT;
3673                 break;
3674         case SONYPI_IOCSBLUE:
3675                 if (copy_from_user(&val8, argp, sizeof(val8))) {
3676                         ret = -EFAULT;
3677                         break;
3678                 }
3679                 __sony_pic_set_bluetoothpower(val8);
3680                 break;
3681         /* FAN Controls */
3682         case SONYPI_IOCGFAN:
3683                 if (sony_pic_get_fanspeed(&val8)) {
3684                         ret = -EIO;
3685                         break;
3686                 }
3687                 if (copy_to_user(argp, &val8, sizeof(val8)))
3688                         ret = -EFAULT;
3689                 break;
3690         case SONYPI_IOCSFAN:
3691                 if (copy_from_user(&val8, argp, sizeof(val8))) {
3692                         ret = -EFAULT;
3693                         break;
3694                 }
3695                 if (sony_pic_set_fanspeed(val8))
3696                         ret = -EIO;
3697                 break;
3698         /* GET Temperature (useful under APM) */
3699         case SONYPI_IOCGTEMP:
3700                 if (ec_read(SONYPI_TEMP_STATUS, &val8)) {
3701                         ret = -EIO;
3702                         break;
3703                 }
3704                 if (copy_to_user(argp, &val8, sizeof(val8)))
3705                         ret = -EFAULT;
3706                 break;
3707         default:
3708                 ret = -EINVAL;
3709         }
3710         mutex_unlock(&spic_dev.lock);
3711         return ret;
3712 }
3713
3714 static const struct file_operations sonypi_misc_fops = {
3715         .owner          = THIS_MODULE,
3716         .read           = sonypi_misc_read,
3717         .poll           = sonypi_misc_poll,
3718         .open           = sonypi_misc_open,
3719         .release        = sonypi_misc_release,
3720         .fasync         = sonypi_misc_fasync,
3721         .unlocked_ioctl = sonypi_misc_ioctl,
3722         .llseek         = noop_llseek,
3723 };
3724
3725 static struct miscdevice sonypi_misc_device = {
3726         .minor          = MISC_DYNAMIC_MINOR,
3727         .name           = "sonypi",
3728         .fops           = &sonypi_misc_fops,
3729 };
3730
3731 static void sonypi_compat_report_event(u8 event)
3732 {
3733         kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event,
3734                         sizeof(event), &sonypi_compat.fifo_lock);
3735         kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
3736         wake_up_interruptible(&sonypi_compat.fifo_proc_list);
3737 }
3738
3739 static int sonypi_compat_init(void)
3740 {
3741         int error;
3742
3743         spin_lock_init(&sonypi_compat.fifo_lock);
3744         error =
3745          kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
3746         if (error) {
3747                 pr_err("kfifo_alloc failed\n");
3748                 return error;
3749         }
3750
3751         init_waitqueue_head(&sonypi_compat.fifo_proc_list);
3752
3753         if (minor != -1)
3754                 sonypi_misc_device.minor = minor;
3755         error = misc_register(&sonypi_misc_device);
3756         if (error) {
3757                 pr_err("misc_register failed\n");
3758                 goto err_free_kfifo;
3759         }
3760         if (minor == -1)
3761                 pr_info("device allocated minor is %d\n",
3762                         sonypi_misc_device.minor);
3763
3764         return 0;
3765
3766 err_free_kfifo:
3767         kfifo_free(&sonypi_compat.fifo);
3768         return error;
3769 }
3770
3771 static void sonypi_compat_exit(void)
3772 {
3773         misc_deregister(&sonypi_misc_device);
3774         kfifo_free(&sonypi_compat.fifo);
3775 }
3776 #else
3777 static int sonypi_compat_init(void) { return 0; }
3778 static void sonypi_compat_exit(void) { }
3779 static void sonypi_compat_report_event(u8 event) { }
3780 #endif /* CONFIG_SONYPI_COMPAT */
3781
3782 /*
3783  * ACPI callbacks
3784  */
3785 static acpi_status
3786 sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
3787 {
3788         u32 i;
3789         struct sony_pic_dev *dev = (struct sony_pic_dev *)context;
3790
3791         switch (resource->type) {
3792         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
3793                 {
3794                         /* start IO enumeration */
3795                         struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
3796                         if (!ioport)
3797                                 return AE_ERROR;
3798
3799                         list_add(&ioport->list, &dev->ioports);
3800                         return AE_OK;
3801                 }
3802
3803         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
3804                 /* end IO enumeration */
3805                 return AE_OK;
3806
3807         case ACPI_RESOURCE_TYPE_IRQ:
3808                 {
3809                         struct acpi_resource_irq *p = &resource->data.irq;
3810                         struct sony_pic_irq *interrupt = NULL;
3811                         if (!p || !p->interrupt_count) {
3812                                 /*
3813                                  * IRQ descriptors may have no IRQ# bits set,
3814                                  * particularly those those w/ _STA disabled
3815                                  */
3816                                 dprintk("Blank IRQ resource\n");
3817                                 return AE_OK;
3818                         }
3819                         for (i = 0; i < p->interrupt_count; i++) {
3820                                 if (!p->interrupts[i]) {
3821                                         pr_warn("Invalid IRQ %d\n",
3822                                                 p->interrupts[i]);
3823                                         continue;
3824                                 }
3825                                 interrupt = kzalloc(sizeof(*interrupt),
3826                                                 GFP_KERNEL);
3827                                 if (!interrupt)
3828                                         return AE_ERROR;
3829
3830                                 list_add(&interrupt->list, &dev->interrupts);
3831                                 interrupt->irq.triggering = p->triggering;
3832                                 interrupt->irq.polarity = p->polarity;
3833                                 interrupt->irq.sharable = p->sharable;
3834                                 interrupt->irq.interrupt_count = 1;
3835                                 interrupt->irq.interrupts[0] = p->interrupts[i];
3836                         }
3837                         return AE_OK;
3838                 }
3839         case ACPI_RESOURCE_TYPE_IO:
3840                 {
3841                         struct acpi_resource_io *io = &resource->data.io;
3842                         struct sony_pic_ioport *ioport =
3843                                 list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
3844                         if (!io) {
3845                                 dprintk("Blank IO resource\n");
3846                                 return AE_OK;
3847                         }
3848
3849                         if (!ioport->io1.minimum) {
3850                                 memcpy(&ioport->io1, io, sizeof(*io));
3851                                 dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
3852                                                 ioport->io1.address_length);
3853                         }
3854                         else if (!ioport->io2.minimum) {
3855                                 memcpy(&ioport->io2, io, sizeof(*io));
3856                                 dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
3857                                                 ioport->io2.address_length);
3858                         }
3859                         else {
3860                                 pr_err("Unknown SPIC Type, more than 2 IO Ports\n");
3861                                 return AE_ERROR;
3862                         }
3863                         return AE_OK;
3864                 }
3865         default:
3866                 dprintk("Resource %d isn't an IRQ nor an IO port\n",
3867                         resource->type);
3868
3869         case ACPI_RESOURCE_TYPE_END_TAG:
3870                 return AE_OK;
3871         }
3872         return AE_CTRL_TERMINATE;
3873 }
3874
3875 static int sony_pic_possible_resources(struct acpi_device *device)
3876 {
3877         int result = 0;
3878         acpi_status status = AE_OK;
3879
3880         if (!device)
3881                 return -EINVAL;
3882
3883         /* get device status */
3884         /* see acpi_pci_link_get_current acpi_pci_link_get_possible */
3885         dprintk("Evaluating _STA\n");
3886         result = acpi_bus_get_status(device);
3887         if (result) {
3888                 pr_warn("Unable to read status\n");
3889                 goto end;
3890         }
3891
3892         if (!device->status.enabled)
3893                 dprintk("Device disabled\n");
3894         else
3895                 dprintk("Device enabled\n");
3896
3897         /*
3898          * Query and parse 'method'
3899          */
3900         dprintk("Evaluating %s\n", METHOD_NAME__PRS);
3901         status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
3902                         sony_pic_read_possible_resource, &spic_dev);
3903         if (ACPI_FAILURE(status)) {
3904                 pr_warn("Failure evaluating %s\n", METHOD_NAME__PRS);
3905                 result = -ENODEV;
3906         }
3907 end:
3908         return result;
3909 }
3910
3911 /*
3912  *  Disable the spic device by calling its _DIS method
3913  */
3914 static int sony_pic_disable(struct acpi_device *device)
3915 {
3916         acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL,
3917                                                NULL);
3918
3919         if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND)
3920                 return -ENXIO;
3921
3922         dprintk("Device disabled\n");
3923         return 0;
3924 }
3925
3926
3927 /*
3928  *  Based on drivers/acpi/pci_link.c:acpi_pci_link_set
3929  *
3930  *  Call _SRS to set current resources
3931  */
3932 static int sony_pic_enable(struct acpi_device *device,
3933                 struct sony_pic_ioport *ioport, struct sony_pic_irq *irq)
3934 {
3935         acpi_status status;
3936         int result = 0;
3937         /* Type 1 resource layout is:
3938          *    IO
3939          *    IO
3940          *    IRQNoFlags
3941          *    End
3942          *
3943          * Type 2 and 3 resource layout is:
3944          *    IO
3945          *    IRQNoFlags
3946          *    End
3947          */
3948         struct {
3949                 struct acpi_resource res1;
3950                 struct acpi_resource res2;
3951                 struct acpi_resource res3;
3952                 struct acpi_resource res4;
3953         } *resource;
3954         struct acpi_buffer buffer = { 0, NULL };
3955
3956         if (!ioport || !irq)
3957                 return -EINVAL;
3958
3959         /* init acpi_buffer */
3960         resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
3961         if (!resource)
3962                 return -ENOMEM;
3963
3964         buffer.length = sizeof(*resource) + 1;
3965         buffer.pointer = resource;
3966
3967         /* setup Type 1 resources */
3968         if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
3969
3970                 /* setup io resources */
3971                 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
3972                 resource->res1.length = sizeof(struct acpi_resource);
3973                 memcpy(&resource->res1.data.io, &ioport->io1,
3974                                 sizeof(struct acpi_resource_io));
3975
3976                 resource->res2.type = ACPI_RESOURCE_TYPE_IO;
3977                 resource->res2.length = sizeof(struct acpi_resource);
3978                 memcpy(&resource->res2.data.io, &ioport->io2,
3979                                 sizeof(struct acpi_resource_io));
3980
3981                 /* setup irq resource */
3982                 resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
3983                 resource->res3.length = sizeof(struct acpi_resource);
3984                 memcpy(&resource->res3.data.irq, &irq->irq,
3985                                 sizeof(struct acpi_resource_irq));
3986                 /* we requested a shared irq */
3987                 resource->res3.data.irq.sharable = ACPI_SHARED;
3988
3989                 resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
3990
3991         }
3992         /* setup Type 2/3 resources */
3993         else {
3994                 /* setup io resource */
3995                 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
3996                 resource->res1.length = sizeof(struct acpi_resource);
3997                 memcpy(&resource->res1.data.io, &ioport->io1,
3998                                 sizeof(struct acpi_resource_io));
3999
4000                 /* setup irq resource */
4001                 resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
4002                 resource->res2.length = sizeof(struct acpi_resource);
4003                 memcpy(&resource->res2.data.irq, &irq->irq,
4004                                 sizeof(struct acpi_resource_irq));
4005                 /* we requested a shared irq */
4006                 resource->res2.data.irq.sharable = ACPI_SHARED;
4007
4008                 resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
4009         }
4010
4011         /* Attempt to set the resource */
4012         dprintk("Evaluating _SRS\n");
4013         status = acpi_set_current_resources(device->handle, &buffer);
4014
4015         /* check for total failure */
4016         if (ACPI_FAILURE(status)) {
4017                 pr_err("Error evaluating _SRS\n");
4018                 result = -ENODEV;
4019                 goto end;
4020         }
4021
4022         /* Necessary device initializations calls (from sonypi) */
4023         sony_pic_call1(0x82);
4024         sony_pic_call2(0x81, 0xff);
4025         sony_pic_call1(compat ? 0x92 : 0x82);
4026
4027 end:
4028         kfree(resource);
4029         return result;
4030 }
4031
4032 /*****************
4033  *
4034  * ISR: some event is available
4035  *
4036  *****************/
4037 static irqreturn_t sony_pic_irq(int irq, void *dev_id)
4038 {
4039         int i, j;
4040         u8 ev = 0;
4041         u8 data_mask = 0;
4042         u8 device_event = 0;
4043
4044         struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
4045
4046         ev = inb_p(dev->cur_ioport->io1.minimum);
4047         if (dev->cur_ioport->io2.minimum)
4048                 data_mask = inb_p(dev->cur_ioport->io2.minimum);
4049         else
4050                 data_mask = inb_p(dev->cur_ioport->io1.minimum +
4051                                 dev->evport_offset);
4052
4053         dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
4054                         ev, data_mask, dev->cur_ioport->io1.minimum,
4055                         dev->evport_offset);
4056
4057         if (ev == 0x00 || ev == 0xff)
4058                 return IRQ_HANDLED;
4059
4060         for (i = 0; dev->event_types[i].mask; i++) {
4061
4062                 if ((data_mask & dev->event_types[i].data) !=
4063                     dev->event_types[i].data)
4064                         continue;
4065
4066                 if (!(mask & dev->event_types[i].mask))
4067                         continue;
4068
4069                 for (j = 0; dev->event_types[i].events[j].event; j++) {
4070                         if (ev == dev->event_types[i].events[j].data) {
4071                                 device_event =
4072                                         dev->event_types[i].events[j].event;
4073                                 /* some events may require ignoring */
4074                                 if (!device_event)
4075                                         return IRQ_HANDLED;
4076                                 goto found;
4077                         }
4078                 }
4079         }
4080         /* Still not able to decode the event try to pass
4081          * it over to the minidriver
4082          */
4083         if (dev->handle_irq && dev->handle_irq(data_mask, ev) == 0)
4084                 return IRQ_HANDLED;
4085
4086         dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
4087                         ev, data_mask, dev->cur_ioport->io1.minimum,
4088                         dev->evport_offset);
4089         return IRQ_HANDLED;
4090
4091 found:
4092         sony_laptop_report_input_event(device_event);
4093         acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
4094         sonypi_compat_report_event(device_event);
4095         return IRQ_HANDLED;
4096 }
4097
4098 /*****************
4099  *
4100  *  ACPI driver
4101  *
4102  *****************/
4103 static int sony_pic_remove(struct acpi_device *device, int type)
4104 {
4105         struct sony_pic_ioport *io, *tmp_io;
4106         struct sony_pic_irq *irq, *tmp_irq;
4107
4108         if (sony_pic_disable(device)) {
4109                 pr_err("Couldn't disable device\n");
4110                 return -ENXIO;
4111         }
4112
4113         free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
4114         release_region(spic_dev.cur_ioport->io1.minimum,
4115                         spic_dev.cur_ioport->io1.address_length);
4116         if (spic_dev.cur_ioport->io2.minimum)
4117                 release_region(spic_dev.cur_ioport->io2.minimum,
4118                                 spic_dev.cur_ioport->io2.address_length);
4119
4120         sonypi_compat_exit();
4121
4122         sony_laptop_remove_input();
4123
4124         /* pf attrs */
4125         sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
4126         sony_pf_remove();
4127
4128         list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
4129                 list_del(&io->list);
4130                 kfree(io);
4131         }
4132         list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
4133                 list_del(&irq->list);
4134                 kfree(irq);
4135         }
4136         spic_dev.cur_ioport = NULL;
4137         spic_dev.cur_irq = NULL;
4138
4139         dprintk(SONY_PIC_DRIVER_NAME " removed.\n");
4140         return 0;
4141 }
4142
4143 static int sony_pic_add(struct acpi_device *device)
4144 {
4145         int result;
4146         struct sony_pic_ioport *io, *tmp_io;
4147         struct sony_pic_irq *irq, *tmp_irq;
4148
4149         pr_info("%s v%s\n", SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
4150
4151         spic_dev.acpi_dev = device;
4152         strcpy(acpi_device_class(device), "sony/hotkey");
4153         sony_pic_detect_device_type(&spic_dev);
4154         mutex_init(&spic_dev.lock);
4155
4156         /* read _PRS resources */
4157         result = sony_pic_possible_resources(device);
4158         if (result) {
4159                 pr_err("Unable to read possible resources\n");
4160                 goto err_free_resources;
4161         }
4162
4163         /* setup input devices and helper fifo */
4164         result = sony_laptop_setup_input(device);
4165         if (result) {
4166                 pr_err("Unable to create input devices\n");
4167                 goto err_free_resources;
4168         }
4169
4170         if (sonypi_compat_init())
4171                 goto err_remove_input;
4172
4173         /* request io port */
4174         list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
4175                 if (request_region(io->io1.minimum, io->io1.address_length,
4176                                         "Sony Programmable I/O Device")) {
4177                         dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
4178                                         io->io1.minimum, io->io1.maximum,
4179                                         io->io1.address_length);
4180                         /* Type 1 have 2 ioports */
4181                         if (io->io2.minimum) {
4182                                 if (request_region(io->io2.minimum,
4183                                                 io->io2.address_length,
4184                                                 "Sony Programmable I/O Device")) {
4185                                         dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
4186                                                         io->io2.minimum, io->io2.maximum,
4187                                                         io->io2.address_length);
4188                                         spic_dev.cur_ioport = io;
4189                                         break;
4190                                 }
4191                                 else {
4192                                         dprintk("Unable to get I/O port2: "
4193                                                         "0x%.4x (0x%.4x) + 0x%.2x\n",
4194                                                         io->io2.minimum, io->io2.maximum,
4195                                                         io->io2.address_length);
4196                                         release_region(io->io1.minimum,
4197                                                         io->io1.address_length);
4198                                 }
4199                         }
4200                         else {
4201                                 spic_dev.cur_ioport = io;
4202                                 break;
4203                         }
4204                 }
4205         }
4206         if (!spic_dev.cur_ioport) {
4207                 pr_err("Failed to request_region\n");
4208                 result = -ENODEV;
4209                 goto err_remove_compat;
4210         }
4211
4212         /* request IRQ */
4213         list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
4214                 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
4215                                         0, "sony-laptop", &spic_dev)) {
4216                         dprintk("IRQ: %d - triggering: %d - "
4217                                         "polarity: %d - shr: %d\n",
4218                                         irq->irq.interrupts[0],
4219                                         irq->irq.triggering,
4220                                         irq->irq.polarity,
4221                                         irq->irq.sharable);
4222                         spic_dev.cur_irq = irq;
4223                         break;
4224                 }
4225         }
4226         if (!spic_dev.cur_irq) {
4227                 pr_err("Failed to request_irq\n");
4228                 result = -ENODEV;
4229                 goto err_release_region;
4230         }
4231
4232         /* set resource status _SRS */
4233         result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
4234         if (result) {
4235                 pr_err("Couldn't enable device\n");
4236                 goto err_free_irq;
4237         }
4238
4239         spic_dev.bluetooth_power = -1;
4240         /* create device attributes */
4241         result = sony_pf_add();
4242         if (result)
4243                 goto err_disable_device;
4244
4245         result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
4246         if (result)
4247                 goto err_remove_pf;
4248
4249         return 0;
4250
4251 err_remove_pf:
4252         sony_pf_remove();
4253
4254 err_disable_device:
4255         sony_pic_disable(device);
4256
4257 err_free_irq:
4258         free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
4259
4260 err_release_region:
4261         release_region(spic_dev.cur_ioport->io1.minimum,
4262                         spic_dev.cur_ioport->io1.address_length);
4263         if (spic_dev.cur_ioport->io2.minimum)
4264                 release_region(spic_dev.cur_ioport->io2.minimum,
4265                                 spic_dev.cur_ioport->io2.address_length);
4266
4267 err_remove_compat:
4268         sonypi_compat_exit();
4269
4270 err_remove_input:
4271         sony_laptop_remove_input();
4272
4273 err_free_resources:
4274         list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
4275                 list_del(&io->list);
4276                 kfree(io);
4277         }
4278         list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
4279                 list_del(&irq->list);
4280                 kfree(irq);
4281         }
4282         spic_dev.cur_ioport = NULL;
4283         spic_dev.cur_irq = NULL;
4284
4285         return result;
4286 }
4287
4288 static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
4289 {
4290         if (sony_pic_disable(device))
4291                 return -ENXIO;
4292         return 0;
4293 }
4294
4295 static int sony_pic_resume(struct acpi_device *device)
4296 {
4297         sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
4298         return 0;
4299 }
4300
4301 static const struct acpi_device_id sony_pic_device_ids[] = {
4302         {SONY_PIC_HID, 0},
4303         {"", 0},
4304 };
4305
4306 static struct acpi_driver sony_pic_driver = {
4307         .name = SONY_PIC_DRIVER_NAME,
4308         .class = SONY_PIC_CLASS,
4309         .ids = sony_pic_device_ids,
4310         .owner = THIS_MODULE,
4311         .ops = {
4312                 .add = sony_pic_add,
4313                 .remove = sony_pic_remove,
4314                 .suspend = sony_pic_suspend,
4315                 .resume = sony_pic_resume,
4316                 },
4317 };
4318
4319 static struct dmi_system_id __initdata sonypi_dmi_table[] = {
4320         {
4321                 .ident = "Sony Vaio",
4322                 .matches = {
4323                         DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
4324                         DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"),
4325                 },
4326         },
4327         {
4328                 .ident = "Sony Vaio",
4329                 .matches = {
4330                         DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
4331                         DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
4332                 },
4333         },
4334         { }
4335 };
4336
4337 static int __init sony_laptop_init(void)
4338 {
4339         int result;
4340
4341         if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
4342                 result = acpi_bus_register_driver(&sony_pic_driver);
4343                 if (result) {
4344                         pr_err("Unable to register SPIC driver\n");
4345                         goto out;
4346                 }
4347                 spic_drv_registered = 1;
4348         }
4349
4350         result = acpi_bus_register_driver(&sony_nc_driver);
4351         if (result) {
4352                 pr_err("Unable to register SNC driver\n");
4353                 goto out_unregister_pic;
4354         }
4355
4356         return 0;
4357
4358 out_unregister_pic:
4359         if (spic_drv_registered)
4360                 acpi_bus_unregister_driver(&sony_pic_driver);
4361 out:
4362         return result;
4363 }
4364
4365 static void __exit sony_laptop_exit(void)
4366 {
4367         acpi_bus_unregister_driver(&sony_nc_driver);
4368         if (spic_drv_registered)
4369                 acpi_bus_unregister_driver(&sony_pic_driver);
4370 }
4371
4372 module_init(sony_laptop_init);
4373 module_exit(sony_laptop_exit);