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