• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ACPI Sony Notebook Control Driver (SNC and SPIC)
3  *
4  * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
5  * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it>
6  *
7  * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
8  * which are copyrighted by their respective authors.
9  *
10  * The SNY6001 driver part is based on the sonypi driver which includes
11  * material from:
12  *
13  * Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net>
14  *
15  * Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
16  *
17  * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
18  *
19  * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
20  *
21  * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
22  *
23  * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
24  *
25  * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
26  *
27  * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
28  *
29  * This program is free software; you can redistribute it and/or modify
30  * it under the terms of the GNU General Public License as published by
31  * the Free Software Foundation; either version 2 of the License, or
32  * (at your option) any later version.
33  *
34  * This program is distributed in the hope that it will be useful,
35  * but WITHOUT ANY WARRANTY; without even the implied warranty of
36  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37  * GNU General Public License for more details.
38  *
39  * You should have received a copy of the GNU General Public License
40  * along with this program; if not, write to the Free Software
41  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42  *
43  */
44 
45 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
46 
47 #include <linux/kernel.h>
48 #include <linux/module.h>
49 #include <linux/moduleparam.h>
50 #include <linux/init.h>
51 #include <linux/types.h>
52 #include <linux/backlight.h>
53 #include <linux/platform_device.h>
54 #include <linux/err.h>
55 #include <linux/dmi.h>
56 #include <linux/pci.h>
57 #include <linux/interrupt.h>
58 #include <linux/delay.h>
59 #include <linux/input.h>
60 #include <linux/kfifo.h>
61 #include <linux/workqueue.h>
62 #include <linux/acpi.h>
63 #include <linux/slab.h>
64 #include <acpi/acpi_drivers.h>
65 #include <acpi/acpi_bus.h>
66 #include <asm/uaccess.h>
67 #include <linux/sonypi.h>
68 #include <linux/sony-laptop.h>
69 #include <linux/rfkill.h>
70 #ifdef CONFIG_SONYPI_COMPAT
71 #include <linux/poll.h>
72 #include <linux/miscdevice.h>
73 #endif
74 
75 #define dprintk(fmt, ...)			\
76 do {						\
77 	if (debug)				\
78 		pr_warn(fmt, ##__VA_ARGS__);	\
79 } while (0)
80 
81 #define SONY_LAPTOP_DRIVER_VERSION	"0.6"
82 
83 #define SONY_NC_CLASS		"sony-nc"
84 #define SONY_NC_HID		"SNY5001"
85 #define SONY_NC_DRIVER_NAME	"Sony Notebook Control Driver"
86 
87 #define SONY_PIC_CLASS		"sony-pic"
88 #define SONY_PIC_HID		"SNY6001"
89 #define SONY_PIC_DRIVER_NAME	"Sony Programmable IO Control Driver"
90 
91 MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
92 MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)");
93 MODULE_LICENSE("GPL");
94 MODULE_VERSION(SONY_LAPTOP_DRIVER_VERSION);
95 
96 static int debug;
97 module_param(debug, int, 0);
98 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
99 		 "the development of this driver");
100 
101 static int no_spic;		/* = 0 */
102 module_param(no_spic, int, 0444);
103 MODULE_PARM_DESC(no_spic,
104 		 "set this if you don't want to enable the SPIC device");
105 
106 static int compat;		/* = 0 */
107 module_param(compat, int, 0444);
108 MODULE_PARM_DESC(compat,
109 		 "set this if you want to enable backward compatibility mode");
110 
111 static unsigned long mask = 0xffffffff;
112 module_param(mask, ulong, 0644);
113 MODULE_PARM_DESC(mask,
114 		 "set this to the mask of event you want to enable (see doc)");
115 
116 static int camera;		/* = 0 */
117 module_param(camera, int, 0444);
118 MODULE_PARM_DESC(camera,
119 		 "set this to 1 to enable Motion Eye camera controls "
120 		 "(only use it if you have a C1VE or C1VN model)");
121 
122 #ifdef CONFIG_SONYPI_COMPAT
123 static int minor = -1;
124 module_param(minor, int, 0);
125 MODULE_PARM_DESC(minor,
126 		 "minor number of the misc device for the SPIC compatibility code, "
127 		 "default is -1 (automatic)");
128 #endif
129 
130 static int kbd_backlight = 1;
131 module_param(kbd_backlight, int, 0444);
132 MODULE_PARM_DESC(kbd_backlight,
133 		 "set this to 0 to disable keyboard backlight, "
134 		 "1 to enable it (default: 0)");
135 
136 static int kbd_backlight_timeout;	/* = 0 */
137 module_param(kbd_backlight_timeout, int, 0444);
138 MODULE_PARM_DESC(kbd_backlight_timeout,
139 		 "set this to 0 to set the default 10 seconds timeout, "
140 		 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
141 		 "(default: 0)");
142 
143 static void sony_nc_kbd_backlight_resume(void);
144 
145 enum sony_nc_rfkill {
146 	SONY_WIFI,
147 	SONY_BLUETOOTH,
148 	SONY_WWAN,
149 	SONY_WIMAX,
150 	N_SONY_RFKILL,
151 };
152 
153 static int sony_rfkill_handle;
154 static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
155 static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
156 static void sony_nc_rfkill_update(void);
157 
158 /*********** Input Devices ***********/
159 
160 #define SONY_LAPTOP_BUF_SIZE	128
161 struct sony_laptop_input_s {
162 	atomic_t		users;
163 	struct input_dev	*jog_dev;
164 	struct input_dev	*key_dev;
165 	struct kfifo		fifo;
166 	spinlock_t		fifo_lock;
167 	struct timer_list	release_key_timer;
168 };
169 
170 static struct sony_laptop_input_s sony_laptop_input = {
171 	.users = ATOMIC_INIT(0),
172 };
173 
174 struct sony_laptop_keypress {
175 	struct input_dev *dev;
176 	int key;
177 };
178 
179 /* Correspondance table between sonypi events
180  * and input layer indexes in the keymap
181  */
182 static int sony_laptop_input_index[] = {
183 	-1,	/*  0 no event */
184 	-1,	/*  1 SONYPI_EVENT_JOGDIAL_DOWN */
185 	-1,	/*  2 SONYPI_EVENT_JOGDIAL_UP */
186 	-1,	/*  3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */
187 	-1,	/*  4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */
188 	-1,	/*  5 SONYPI_EVENT_JOGDIAL_PRESSED */
189 	-1,	/*  6 SONYPI_EVENT_JOGDIAL_RELEASED */
190 	 0,	/*  7 SONYPI_EVENT_CAPTURE_PRESSED */
191 	 1,	/*  8 SONYPI_EVENT_CAPTURE_RELEASED */
192 	 2,	/*  9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
193 	 3,	/* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
194 	 4,	/* 11 SONYPI_EVENT_FNKEY_ESC */
195 	 5,	/* 12 SONYPI_EVENT_FNKEY_F1 */
196 	 6,	/* 13 SONYPI_EVENT_FNKEY_F2 */
197 	 7,	/* 14 SONYPI_EVENT_FNKEY_F3 */
198 	 8,	/* 15 SONYPI_EVENT_FNKEY_F4 */
199 	 9,	/* 16 SONYPI_EVENT_FNKEY_F5 */
200 	10,	/* 17 SONYPI_EVENT_FNKEY_F6 */
201 	11,	/* 18 SONYPI_EVENT_FNKEY_F7 */
202 	12,	/* 19 SONYPI_EVENT_FNKEY_F8 */
203 	13,	/* 20 SONYPI_EVENT_FNKEY_F9 */
204 	14,	/* 21 SONYPI_EVENT_FNKEY_F10 */
205 	15,	/* 22 SONYPI_EVENT_FNKEY_F11 */
206 	16,	/* 23 SONYPI_EVENT_FNKEY_F12 */
207 	17,	/* 24 SONYPI_EVENT_FNKEY_1 */
208 	18,	/* 25 SONYPI_EVENT_FNKEY_2 */
209 	19,	/* 26 SONYPI_EVENT_FNKEY_D */
210 	20,	/* 27 SONYPI_EVENT_FNKEY_E */
211 	21,	/* 28 SONYPI_EVENT_FNKEY_F */
212 	22,	/* 29 SONYPI_EVENT_FNKEY_S */
213 	23,	/* 30 SONYPI_EVENT_FNKEY_B */
214 	24,	/* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */
215 	25,	/* 32 SONYPI_EVENT_PKEY_P1 */
216 	26,	/* 33 SONYPI_EVENT_PKEY_P2 */
217 	27,	/* 34 SONYPI_EVENT_PKEY_P3 */
218 	28,	/* 35 SONYPI_EVENT_BACK_PRESSED */
219 	-1,	/* 36 SONYPI_EVENT_LID_CLOSED */
220 	-1,	/* 37 SONYPI_EVENT_LID_OPENED */
221 	29,	/* 38 SONYPI_EVENT_BLUETOOTH_ON */
222 	30,	/* 39 SONYPI_EVENT_BLUETOOTH_OFF */
223 	31,	/* 40 SONYPI_EVENT_HELP_PRESSED */
224 	32,	/* 41 SONYPI_EVENT_FNKEY_ONLY */
225 	33,	/* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */
226 	34,	/* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */
227 	35,	/* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
228 	36,	/* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
229 	37,	/* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
230 	38,	/* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */
231 	39,	/* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
232 	40,	/* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
233 	41,	/* 50 SONYPI_EVENT_ZOOM_PRESSED */
234 	42,	/* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */
235 	43,	/* 52 SONYPI_EVENT_MEYE_FACE */
236 	44,	/* 53 SONYPI_EVENT_MEYE_OPPOSITE */
237 	45,	/* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */
238 	46,	/* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */
239 	-1,	/* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */
240 	-1,	/* 57 SONYPI_EVENT_BATTERY_INSERT */
241 	-1,	/* 58 SONYPI_EVENT_BATTERY_REMOVE */
242 	-1,	/* 59 SONYPI_EVENT_FNKEY_RELEASED */
243 	47,	/* 60 SONYPI_EVENT_WIRELESS_ON */
244 	48,	/* 61 SONYPI_EVENT_WIRELESS_OFF */
245 	49,	/* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */
246 	50,	/* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */
247 	51,	/* 64 SONYPI_EVENT_CD_EJECT_PRESSED */
248 	52,	/* 65 SONYPI_EVENT_MODEKEY_PRESSED */
249 	53,	/* 66 SONYPI_EVENT_PKEY_P4 */
250 	54,	/* 67 SONYPI_EVENT_PKEY_P5 */
251 	55,	/* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */
252 	56,	/* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */
253 	57,	/* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
254 	-1,	/* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
255 	58,	/* 72 SONYPI_EVENT_MEDIA_PRESSED */
256 	59,	/* 72 SONYPI_EVENT_VENDOR_PRESSED */
257 };
258 
259 static int sony_laptop_input_keycode_map[] = {
260 	KEY_CAMERA,	/*  0 SONYPI_EVENT_CAPTURE_PRESSED */
261 	KEY_RESERVED,	/*  1 SONYPI_EVENT_CAPTURE_RELEASED */
262 	KEY_RESERVED,	/*  2 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
263 	KEY_RESERVED,	/*  3 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
264 	KEY_FN_ESC,	/*  4 SONYPI_EVENT_FNKEY_ESC */
265 	KEY_FN_F1,	/*  5 SONYPI_EVENT_FNKEY_F1 */
266 	KEY_FN_F2,	/*  6 SONYPI_EVENT_FNKEY_F2 */
267 	KEY_FN_F3,	/*  7 SONYPI_EVENT_FNKEY_F3 */
268 	KEY_FN_F4,	/*  8 SONYPI_EVENT_FNKEY_F4 */
269 	KEY_FN_F5,	/*  9 SONYPI_EVENT_FNKEY_F5 */
270 	KEY_FN_F6,	/* 10 SONYPI_EVENT_FNKEY_F6 */
271 	KEY_FN_F7,	/* 11 SONYPI_EVENT_FNKEY_F7 */
272 	KEY_FN_F8,	/* 12 SONYPI_EVENT_FNKEY_F8 */
273 	KEY_FN_F9,	/* 13 SONYPI_EVENT_FNKEY_F9 */
274 	KEY_FN_F10,	/* 14 SONYPI_EVENT_FNKEY_F10 */
275 	KEY_FN_F11,	/* 15 SONYPI_EVENT_FNKEY_F11 */
276 	KEY_FN_F12,	/* 16 SONYPI_EVENT_FNKEY_F12 */
277 	KEY_FN_F1,	/* 17 SONYPI_EVENT_FNKEY_1 */
278 	KEY_FN_F2,	/* 18 SONYPI_EVENT_FNKEY_2 */
279 	KEY_FN_D,	/* 19 SONYPI_EVENT_FNKEY_D */
280 	KEY_FN_E,	/* 20 SONYPI_EVENT_FNKEY_E */
281 	KEY_FN_F,	/* 21 SONYPI_EVENT_FNKEY_F */
282 	KEY_FN_S,	/* 22 SONYPI_EVENT_FNKEY_S */
283 	KEY_FN_B,	/* 23 SONYPI_EVENT_FNKEY_B */
284 	KEY_BLUETOOTH,	/* 24 SONYPI_EVENT_BLUETOOTH_PRESSED */
285 	KEY_PROG1,	/* 25 SONYPI_EVENT_PKEY_P1 */
286 	KEY_PROG2,	/* 26 SONYPI_EVENT_PKEY_P2 */
287 	KEY_PROG3,	/* 27 SONYPI_EVENT_PKEY_P3 */
288 	KEY_BACK,	/* 28 SONYPI_EVENT_BACK_PRESSED */
289 	KEY_BLUETOOTH,	/* 29 SONYPI_EVENT_BLUETOOTH_ON */
290 	KEY_BLUETOOTH,	/* 30 SONYPI_EVENT_BLUETOOTH_OFF */
291 	KEY_HELP,	/* 31 SONYPI_EVENT_HELP_PRESSED */
292 	KEY_FN,		/* 32 SONYPI_EVENT_FNKEY_ONLY */
293 	KEY_RESERVED,	/* 33 SONYPI_EVENT_JOGDIAL_FAST_DOWN */
294 	KEY_RESERVED,	/* 34 SONYPI_EVENT_JOGDIAL_FAST_UP */
295 	KEY_RESERVED,	/* 35 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
296 	KEY_RESERVED,	/* 36 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
297 	KEY_RESERVED,	/* 37 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
298 	KEY_RESERVED,	/* 38 SONYPI_EVENT_JOGDIAL_VFAST_UP */
299 	KEY_RESERVED,	/* 39 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
300 	KEY_RESERVED,	/* 40 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
301 	KEY_ZOOM,	/* 41 SONYPI_EVENT_ZOOM_PRESSED */
302 	BTN_THUMB,	/* 42 SONYPI_EVENT_THUMBPHRASE_PRESSED */
303 	KEY_RESERVED,	/* 43 SONYPI_EVENT_MEYE_FACE */
304 	KEY_RESERVED,	/* 44 SONYPI_EVENT_MEYE_OPPOSITE */
305 	KEY_RESERVED,	/* 45 SONYPI_EVENT_MEMORYSTICK_INSERT */
306 	KEY_RESERVED,	/* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */
307 	KEY_WLAN,	/* 47 SONYPI_EVENT_WIRELESS_ON */
308 	KEY_WLAN,	/* 48 SONYPI_EVENT_WIRELESS_OFF */
309 	KEY_ZOOMIN,	/* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */
310 	KEY_ZOOMOUT,	/* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */
311 	KEY_EJECTCD,	/* 51 SONYPI_EVENT_CD_EJECT_PRESSED */
312 	KEY_F13,	/* 52 SONYPI_EVENT_MODEKEY_PRESSED */
313 	KEY_PROG4,	/* 53 SONYPI_EVENT_PKEY_P4 */
314 	KEY_F14,	/* 54 SONYPI_EVENT_PKEY_P5 */
315 	KEY_F15,	/* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */
316 	KEY_VOLUMEUP,	/* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
317 	KEY_VOLUMEDOWN,	/* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
318 	KEY_MEDIA,	/* 58 SONYPI_EVENT_MEDIA_PRESSED */
319 	KEY_VENDOR,	/* 59 SONYPI_EVENT_VENDOR_PRESSED */
320 };
321 
322 /* release buttons after a short delay if pressed */
do_sony_laptop_release_key(unsigned long unused)323 static void do_sony_laptop_release_key(unsigned long unused)
324 {
325 	struct sony_laptop_keypress kp;
326 	unsigned long flags;
327 
328 	spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags);
329 
330 	if (kfifo_out(&sony_laptop_input.fifo,
331 		      (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
332 		input_report_key(kp.dev, kp.key, 0);
333 		input_sync(kp.dev);
334 	}
335 
336 	/* If there is something in the fifo schedule next release. */
337 	if (kfifo_len(&sony_laptop_input.fifo) != 0)
338 		mod_timer(&sony_laptop_input.release_key_timer,
339 			  jiffies + msecs_to_jiffies(10));
340 
341 	spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags);
342 }
343 
344 /* forward event to the input subsystem */
sony_laptop_report_input_event(u8 event)345 static void sony_laptop_report_input_event(u8 event)
346 {
347 	struct input_dev *jog_dev = sony_laptop_input.jog_dev;
348 	struct input_dev *key_dev = sony_laptop_input.key_dev;
349 	struct sony_laptop_keypress kp = { NULL };
350 	int scancode = -1;
351 
352 	if (event == SONYPI_EVENT_FNKEY_RELEASED ||
353 			event == SONYPI_EVENT_ANYBUTTON_RELEASED) {
354 		/* Nothing, not all VAIOs generate this event */
355 		return;
356 	}
357 
358 	/* report events */
359 	switch (event) {
360 	/* jog_dev events */
361 	case SONYPI_EVENT_JOGDIAL_UP:
362 	case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
363 		input_report_rel(jog_dev, REL_WHEEL, 1);
364 		input_sync(jog_dev);
365 		return;
366 
367 	case SONYPI_EVENT_JOGDIAL_DOWN:
368 	case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
369 		input_report_rel(jog_dev, REL_WHEEL, -1);
370 		input_sync(jog_dev);
371 		return;
372 
373 	/* key_dev events */
374 	case SONYPI_EVENT_JOGDIAL_PRESSED:
375 		kp.key = BTN_MIDDLE;
376 		kp.dev = jog_dev;
377 		break;
378 
379 	default:
380 		if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
381 			dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
382 			break;
383 		}
384 		if ((scancode = sony_laptop_input_index[event]) != -1) {
385 			kp.key = sony_laptop_input_keycode_map[scancode];
386 			if (kp.key != KEY_UNKNOWN)
387 				kp.dev = key_dev;
388 		}
389 		break;
390 	}
391 
392 	if (kp.dev) {
393 		/* if we have a scancode we emit it so we can always
394 		    remap the key */
395 		if (scancode != -1)
396 			input_event(kp.dev, EV_MSC, MSC_SCAN, scancode);
397 		input_report_key(kp.dev, kp.key, 1);
398 		input_sync(kp.dev);
399 
400 		/* schedule key release */
401 		kfifo_in_locked(&sony_laptop_input.fifo,
402 				(unsigned char *)&kp, sizeof(kp),
403 				&sony_laptop_input.fifo_lock);
404 		mod_timer(&sony_laptop_input.release_key_timer,
405 			  jiffies + msecs_to_jiffies(10));
406 	} else
407 		dprintk("unknown input event %.2x\n", event);
408 }
409 
sony_laptop_setup_input(struct acpi_device * acpi_device)410 static int sony_laptop_setup_input(struct acpi_device *acpi_device)
411 {
412 	struct input_dev *jog_dev;
413 	struct input_dev *key_dev;
414 	int i;
415 	int error;
416 
417 	/* don't run again if already initialized */
418 	if (atomic_add_return(1, &sony_laptop_input.users) > 1)
419 		return 0;
420 
421 	/* kfifo */
422 	spin_lock_init(&sony_laptop_input.fifo_lock);
423 	error = kfifo_alloc(&sony_laptop_input.fifo,
424 			    SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
425 	if (error) {
426 		pr_err("kfifo_alloc failed\n");
427 		goto err_dec_users;
428 	}
429 
430 	setup_timer(&sony_laptop_input.release_key_timer,
431 		    do_sony_laptop_release_key, 0);
432 
433 	/* input keys */
434 	key_dev = input_allocate_device();
435 	if (!key_dev) {
436 		error = -ENOMEM;
437 		goto err_free_kfifo;
438 	}
439 
440 	key_dev->name = "Sony Vaio Keys";
441 	key_dev->id.bustype = BUS_ISA;
442 	key_dev->id.vendor = PCI_VENDOR_ID_SONY;
443 	key_dev->dev.parent = &acpi_device->dev;
444 
445 	/* Initialize the Input Drivers: special keys */
446 	input_set_capability(key_dev, EV_MSC, MSC_SCAN);
447 
448 	__set_bit(EV_KEY, key_dev->evbit);
449 	key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
450 	key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
451 	key_dev->keycode = &sony_laptop_input_keycode_map;
452 	for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++)
453 		__set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
454 	__clear_bit(KEY_RESERVED, key_dev->keybit);
455 
456 	error = input_register_device(key_dev);
457 	if (error)
458 		goto err_free_keydev;
459 
460 	sony_laptop_input.key_dev = key_dev;
461 
462 	/* jogdial */
463 	jog_dev = input_allocate_device();
464 	if (!jog_dev) {
465 		error = -ENOMEM;
466 		goto err_unregister_keydev;
467 	}
468 
469 	jog_dev->name = "Sony Vaio Jogdial";
470 	jog_dev->id.bustype = BUS_ISA;
471 	jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
472 	jog_dev->dev.parent = &acpi_device->dev;
473 
474 	input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
475 	input_set_capability(jog_dev, EV_REL, REL_WHEEL);
476 
477 	error = input_register_device(jog_dev);
478 	if (error)
479 		goto err_free_jogdev;
480 
481 	sony_laptop_input.jog_dev = jog_dev;
482 
483 	return 0;
484 
485 err_free_jogdev:
486 	input_free_device(jog_dev);
487 
488 err_unregister_keydev:
489 	input_unregister_device(key_dev);
490 	/* to avoid kref underflow below at input_free_device */
491 	key_dev = NULL;
492 
493 err_free_keydev:
494 	input_free_device(key_dev);
495 
496 err_free_kfifo:
497 	kfifo_free(&sony_laptop_input.fifo);
498 
499 err_dec_users:
500 	atomic_dec(&sony_laptop_input.users);
501 	return error;
502 }
503 
sony_laptop_remove_input(void)504 static void sony_laptop_remove_input(void)
505 {
506 	struct sony_laptop_keypress kp = { NULL };
507 
508 	/* Cleanup only after the last user has gone */
509 	if (!atomic_dec_and_test(&sony_laptop_input.users))
510 		return;
511 
512 	del_timer_sync(&sony_laptop_input.release_key_timer);
513 
514 	/*
515 	 * Generate key-up events for remaining keys. Note that we don't
516 	 * need locking since nobody is adding new events to the kfifo.
517 	 */
518 	while (kfifo_out(&sony_laptop_input.fifo,
519 			 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
520 		input_report_key(kp.dev, kp.key, 0);
521 		input_sync(kp.dev);
522 	}
523 
524 	/* destroy input devs */
525 	input_unregister_device(sony_laptop_input.key_dev);
526 	sony_laptop_input.key_dev = NULL;
527 
528 	if (sony_laptop_input.jog_dev) {
529 		input_unregister_device(sony_laptop_input.jog_dev);
530 		sony_laptop_input.jog_dev = NULL;
531 	}
532 
533 	kfifo_free(&sony_laptop_input.fifo);
534 }
535 
536 /*********** Platform Device ***********/
537 
538 static atomic_t sony_pf_users = ATOMIC_INIT(0);
539 static struct platform_driver sony_pf_driver = {
540 	.driver = {
541 		   .name = "sony-laptop",
542 		   .owner = THIS_MODULE,
543 		   }
544 };
545 static struct platform_device *sony_pf_device;
546 
sony_pf_add(void)547 static int sony_pf_add(void)
548 {
549 	int ret = 0;
550 
551 	/* don't run again if already initialized */
552 	if (atomic_add_return(1, &sony_pf_users) > 1)
553 		return 0;
554 
555 	ret = platform_driver_register(&sony_pf_driver);
556 	if (ret)
557 		goto out;
558 
559 	sony_pf_device = platform_device_alloc("sony-laptop", -1);
560 	if (!sony_pf_device) {
561 		ret = -ENOMEM;
562 		goto out_platform_registered;
563 	}
564 
565 	ret = platform_device_add(sony_pf_device);
566 	if (ret)
567 		goto out_platform_alloced;
568 
569 	return 0;
570 
571       out_platform_alloced:
572 	platform_device_put(sony_pf_device);
573 	sony_pf_device = NULL;
574       out_platform_registered:
575 	platform_driver_unregister(&sony_pf_driver);
576       out:
577 	atomic_dec(&sony_pf_users);
578 	return ret;
579 }
580 
sony_pf_remove(void)581 static void sony_pf_remove(void)
582 {
583 	/* deregister only after the last user has gone */
584 	if (!atomic_dec_and_test(&sony_pf_users))
585 		return;
586 
587 	platform_device_unregister(sony_pf_device);
588 	platform_driver_unregister(&sony_pf_driver);
589 }
590 
591 /*********** SNC (SNY5001) Device ***********/
592 
593 /* the device uses 1-based values, while the backlight subsystem uses
594    0-based values */
595 #define SONY_MAX_BRIGHTNESS	8
596 
597 #define SNC_VALIDATE_IN		0
598 #define SNC_VALIDATE_OUT	1
599 
600 static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
601 			      char *);
602 static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
603 			       const char *, size_t);
604 static int boolean_validate(const int, const int);
605 static int brightness_default_validate(const int, const int);
606 
607 struct sony_nc_value {
608 	char *name;		/* name of the entry */
609 	char **acpiget;		/* names of the ACPI get function */
610 	char **acpiset;		/* names of the ACPI set function */
611 	int (*validate)(const int, const int);	/* input/output validation */
612 	int value;		/* current setting */
613 	int valid;		/* Has ever been set */
614 	int debug;		/* active only in debug mode ? */
615 	struct device_attribute devattr;	/* sysfs attribute */
616 };
617 
618 #define SNC_HANDLE_NAMES(_name, _values...) \
619 	static char *snc_##_name[] = { _values, NULL }
620 
621 #define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \
622 	{ \
623 		.name		= __stringify(_name), \
624 		.acpiget	= _getters, \
625 		.acpiset	= _setters, \
626 		.validate	= _validate, \
627 		.debug		= _debug, \
628 		.devattr	= __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \
629 	}
630 
631 #define SNC_HANDLE_NULL	{ .name = NULL }
632 
633 SNC_HANDLE_NAMES(fnkey_get, "GHKE");
634 
635 SNC_HANDLE_NAMES(brightness_def_get, "GPBR");
636 SNC_HANDLE_NAMES(brightness_def_set, "SPBR");
637 
638 SNC_HANDLE_NAMES(cdpower_get, "GCDP");
639 SNC_HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
640 
641 SNC_HANDLE_NAMES(audiopower_get, "GAZP");
642 SNC_HANDLE_NAMES(audiopower_set, "AZPW");
643 
644 SNC_HANDLE_NAMES(lanpower_get, "GLNP");
645 SNC_HANDLE_NAMES(lanpower_set, "LNPW");
646 
647 SNC_HANDLE_NAMES(lidstate_get, "GLID");
648 
649 SNC_HANDLE_NAMES(indicatorlamp_get, "GILS");
650 SNC_HANDLE_NAMES(indicatorlamp_set, "SILS");
651 
652 SNC_HANDLE_NAMES(gainbass_get, "GMGB");
653 SNC_HANDLE_NAMES(gainbass_set, "CMGB");
654 
655 SNC_HANDLE_NAMES(PID_get, "GPID");
656 
657 SNC_HANDLE_NAMES(CTR_get, "GCTR");
658 SNC_HANDLE_NAMES(CTR_set, "SCTR");
659 
660 SNC_HANDLE_NAMES(PCR_get, "GPCR");
661 SNC_HANDLE_NAMES(PCR_set, "SPCR");
662 
663 SNC_HANDLE_NAMES(CMI_get, "GCMI");
664 SNC_HANDLE_NAMES(CMI_set, "SCMI");
665 
666 static struct sony_nc_value sony_nc_values[] = {
667 	SNC_HANDLE(brightness_default, snc_brightness_def_get,
668 			snc_brightness_def_set, brightness_default_validate, 0),
669 	SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
670 	SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
671 	SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
672 			boolean_validate, 0),
673 	SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
674 			boolean_validate, 1),
675 	SNC_HANDLE(lidstate, snc_lidstate_get, NULL,
676 			boolean_validate, 0),
677 	SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set,
678 			boolean_validate, 0),
679 	SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set,
680 			boolean_validate, 0),
681 	/* unknown methods */
682 	SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1),
683 	SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
684 	SNC_HANDLE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
685 	SNC_HANDLE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
686 	SNC_HANDLE_NULL
687 };
688 
689 static acpi_handle sony_nc_acpi_handle;
690 static struct acpi_device *sony_nc_acpi_device = NULL;
691 
692 /*
693  * acpi_evaluate_object wrappers
694  */
acpi_callgetfunc(acpi_handle handle,char * name,int * result)695 static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
696 {
697 	struct acpi_buffer output;
698 	union acpi_object out_obj;
699 	acpi_status status;
700 
701 	output.length = sizeof(out_obj);
702 	output.pointer = &out_obj;
703 
704 	status = acpi_evaluate_object(handle, name, NULL, &output);
705 	if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) {
706 		*result = out_obj.integer.value;
707 		return 0;
708 	}
709 
710 	pr_warn("acpi_callreadfunc failed\n");
711 
712 	return -1;
713 }
714 
acpi_callsetfunc(acpi_handle handle,char * name,int value,int * result)715 static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
716 			    int *result)
717 {
718 	struct acpi_object_list params;
719 	union acpi_object in_obj;
720 	struct acpi_buffer output;
721 	union acpi_object out_obj;
722 	acpi_status status;
723 
724 	params.count = 1;
725 	params.pointer = &in_obj;
726 	in_obj.type = ACPI_TYPE_INTEGER;
727 	in_obj.integer.value = value;
728 
729 	output.length = sizeof(out_obj);
730 	output.pointer = &out_obj;
731 
732 	status = acpi_evaluate_object(handle, name, &params, &output);
733 	if (status == AE_OK) {
734 		if (result != NULL) {
735 			if (out_obj.type != ACPI_TYPE_INTEGER) {
736 				pr_warn("acpi_evaluate_object bad return type\n");
737 				return -1;
738 			}
739 			*result = out_obj.integer.value;
740 		}
741 		return 0;
742 	}
743 
744 	pr_warn("acpi_evaluate_object failed\n");
745 
746 	return -1;
747 }
748 
749 struct sony_nc_handles {
750 	u16 cap[0x10];
751 	struct device_attribute devattr;
752 };
753 
754 static struct sony_nc_handles *handles;
755 
sony_nc_handles_show(struct device * dev,struct device_attribute * attr,char * buffer)756 static ssize_t sony_nc_handles_show(struct device *dev,
757 		struct device_attribute *attr, char *buffer)
758 {
759 	ssize_t len = 0;
760 	int i;
761 
762 	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
763 		len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
764 				handles->cap[i]);
765 	}
766 	len += snprintf(buffer + len, PAGE_SIZE - len, "\n");
767 
768 	return len;
769 }
770 
sony_nc_handles_setup(struct platform_device * pd)771 static int sony_nc_handles_setup(struct platform_device *pd)
772 {
773 	int i;
774 	int result;
775 
776 	handles = kzalloc(sizeof(*handles), GFP_KERNEL);
777 	if (!handles)
778 		return -ENOMEM;
779 
780 	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
781 		if (!acpi_callsetfunc(sony_nc_acpi_handle,
782 					"SN00", i + 0x20, &result)) {
783 			dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
784 					result, i);
785 			handles->cap[i] = result;
786 		}
787 	}
788 
789 	if (debug) {
790 		sysfs_attr_init(&handles->devattr.attr);
791 		handles->devattr.attr.name = "handles";
792 		handles->devattr.attr.mode = S_IRUGO;
793 		handles->devattr.show = sony_nc_handles_show;
794 
795 		/* allow reading capabilities via sysfs */
796 		if (device_create_file(&pd->dev, &handles->devattr)) {
797 			kfree(handles);
798 			handles = NULL;
799 			return -1;
800 		}
801 	}
802 
803 	return 0;
804 }
805 
sony_nc_handles_cleanup(struct platform_device * pd)806 static int sony_nc_handles_cleanup(struct platform_device *pd)
807 {
808 	if (handles) {
809 		if (debug)
810 			device_remove_file(&pd->dev, &handles->devattr);
811 		kfree(handles);
812 		handles = NULL;
813 	}
814 	return 0;
815 }
816 
sony_find_snc_handle(int handle)817 static int sony_find_snc_handle(int handle)
818 {
819 	int i;
820 
821 	/* not initialized yet, return early */
822 	if (!handles)
823 		return -1;
824 
825 	for (i = 0; i < 0x10; i++) {
826 		if (handles->cap[i] == handle) {
827 			dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
828 					handle, i);
829 			return i;
830 		}
831 	}
832 	dprintk("handle 0x%.4x not found\n", handle);
833 	return -1;
834 }
835 
sony_call_snc_handle(int handle,int argument,int * result)836 static int sony_call_snc_handle(int handle, int argument, int *result)
837 {
838 	int ret = 0;
839 	int offset = sony_find_snc_handle(handle);
840 
841 	if (offset < 0)
842 		return -1;
843 
844 	ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
845 			result);
846 	dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument,
847 			*result);
848 	return ret;
849 }
850 
851 /*
852  * sony_nc_values input/output validate functions
853  */
854 
855 /* brightness_default_validate:
856  *
857  * manipulate input output values to keep consistency with the
858  * backlight framework for which brightness values are 0-based.
859  */
brightness_default_validate(const int direction,const int value)860 static int brightness_default_validate(const int direction, const int value)
861 {
862 	switch (direction) {
863 		case SNC_VALIDATE_OUT:
864 			return value - 1;
865 		case SNC_VALIDATE_IN:
866 			if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
867 				return value + 1;
868 	}
869 	return -EINVAL;
870 }
871 
872 /* boolean_validate:
873  *
874  * on input validate boolean values 0/1, on output just pass the
875  * received value.
876  */
boolean_validate(const int direction,const int value)877 static int boolean_validate(const int direction, const int value)
878 {
879 	if (direction == SNC_VALIDATE_IN) {
880 		if (value != 0 && value != 1)
881 			return -EINVAL;
882 	}
883 	return value;
884 }
885 
886 /*
887  * Sysfs show/store common to all sony_nc_values
888  */
sony_nc_sysfs_show(struct device * dev,struct device_attribute * attr,char * buffer)889 static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
890 			      char *buffer)
891 {
892 	int value;
893 	struct sony_nc_value *item =
894 	    container_of(attr, struct sony_nc_value, devattr);
895 
896 	if (!*item->acpiget)
897 		return -EIO;
898 
899 	if (acpi_callgetfunc(sony_nc_acpi_handle, *item->acpiget, &value) < 0)
900 		return -EIO;
901 
902 	if (item->validate)
903 		value = item->validate(SNC_VALIDATE_OUT, value);
904 
905 	return snprintf(buffer, PAGE_SIZE, "%d\n", value);
906 }
907 
sony_nc_sysfs_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)908 static ssize_t sony_nc_sysfs_store(struct device *dev,
909 			       struct device_attribute *attr,
910 			       const char *buffer, size_t count)
911 {
912 	int value;
913 	struct sony_nc_value *item =
914 	    container_of(attr, struct sony_nc_value, devattr);
915 
916 	if (!item->acpiset)
917 		return -EIO;
918 
919 	if (count > 31)
920 		return -EINVAL;
921 
922 	value = simple_strtoul(buffer, NULL, 10);
923 
924 	if (item->validate)
925 		value = item->validate(SNC_VALIDATE_IN, value);
926 
927 	if (value < 0)
928 		return value;
929 
930 	if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0)
931 		return -EIO;
932 	item->value = value;
933 	item->valid = 1;
934 	return count;
935 }
936 
937 
938 /*
939  * Backlight device
940  */
941 struct sony_backlight_props {
942 	struct backlight_device *dev;
943 	int			handle;
944 	u8			offset;
945 	u8			maxlvl;
946 };
947 struct sony_backlight_props sony_bl_props;
948 
sony_backlight_update_status(struct backlight_device * bd)949 static int sony_backlight_update_status(struct backlight_device *bd)
950 {
951 	return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
952 				bd->props.brightness + 1, NULL);
953 }
954 
sony_backlight_get_brightness(struct backlight_device * bd)955 static int sony_backlight_get_brightness(struct backlight_device *bd)
956 {
957 	int value;
958 
959 	if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value))
960 		return 0;
961 	/* brightness levels are 1-based, while backlight ones are 0-based */
962 	return value - 1;
963 }
964 
sony_nc_get_brightness_ng(struct backlight_device * bd)965 static int sony_nc_get_brightness_ng(struct backlight_device *bd)
966 {
967 	int result;
968 	struct sony_backlight_props *sdev =
969 		(struct sony_backlight_props *)bl_get_data(bd);
970 
971 	sony_call_snc_handle(sdev->handle, 0x0200, &result);
972 
973 	return (result & 0xff) - sdev->offset;
974 }
975 
sony_nc_update_status_ng(struct backlight_device * bd)976 static int sony_nc_update_status_ng(struct backlight_device *bd)
977 {
978 	int value, result;
979 	struct sony_backlight_props *sdev =
980 		(struct sony_backlight_props *)bl_get_data(bd);
981 
982 	value = bd->props.brightness + sdev->offset;
983 	if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
984 		return -EIO;
985 
986 	return value;
987 }
988 
989 static const struct backlight_ops sony_backlight_ops = {
990 	.options = BL_CORE_SUSPENDRESUME,
991 	.update_status = sony_backlight_update_status,
992 	.get_brightness = sony_backlight_get_brightness,
993 };
994 static const struct backlight_ops sony_backlight_ng_ops = {
995 	.options = BL_CORE_SUSPENDRESUME,
996 	.update_status = sony_nc_update_status_ng,
997 	.get_brightness = sony_nc_get_brightness_ng,
998 };
999 
1000 /*
1001  * New SNC-only Vaios event mapping to driver known keys
1002  */
1003 struct sony_nc_event {
1004 	u8	data;
1005 	u8	event;
1006 };
1007 
1008 static struct sony_nc_event sony_100_events[] = {
1009 	{ 0x90, SONYPI_EVENT_PKEY_P1 },
1010 	{ 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
1011 	{ 0x91, SONYPI_EVENT_PKEY_P2 },
1012 	{ 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
1013 	{ 0x81, SONYPI_EVENT_FNKEY_F1 },
1014 	{ 0x01, SONYPI_EVENT_FNKEY_RELEASED },
1015 	{ 0x82, SONYPI_EVENT_FNKEY_F2 },
1016 	{ 0x02, SONYPI_EVENT_FNKEY_RELEASED },
1017 	{ 0x83, SONYPI_EVENT_FNKEY_F3 },
1018 	{ 0x03, SONYPI_EVENT_FNKEY_RELEASED },
1019 	{ 0x84, SONYPI_EVENT_FNKEY_F4 },
1020 	{ 0x04, SONYPI_EVENT_FNKEY_RELEASED },
1021 	{ 0x85, SONYPI_EVENT_FNKEY_F5 },
1022 	{ 0x05, SONYPI_EVENT_FNKEY_RELEASED },
1023 	{ 0x86, SONYPI_EVENT_FNKEY_F6 },
1024 	{ 0x06, SONYPI_EVENT_FNKEY_RELEASED },
1025 	{ 0x87, SONYPI_EVENT_FNKEY_F7 },
1026 	{ 0x07, SONYPI_EVENT_FNKEY_RELEASED },
1027 	{ 0x89, SONYPI_EVENT_FNKEY_F9 },
1028 	{ 0x09, SONYPI_EVENT_FNKEY_RELEASED },
1029 	{ 0x8A, SONYPI_EVENT_FNKEY_F10 },
1030 	{ 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
1031 	{ 0x8C, SONYPI_EVENT_FNKEY_F12 },
1032 	{ 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
1033 	{ 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
1034 	{ 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
1035 	{ 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
1036 	{ 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
1037 	{ 0xa1, SONYPI_EVENT_MEDIA_PRESSED },
1038 	{ 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED },
1039 	{ 0xa4, SONYPI_EVENT_CD_EJECT_PRESSED },
1040 	{ 0x24, SONYPI_EVENT_ANYBUTTON_RELEASED },
1041 	{ 0xa5, SONYPI_EVENT_VENDOR_PRESSED },
1042 	{ 0x25, SONYPI_EVENT_ANYBUTTON_RELEASED },
1043 	{ 0xa6, SONYPI_EVENT_HELP_PRESSED },
1044 	{ 0x26, SONYPI_EVENT_ANYBUTTON_RELEASED },
1045 	{ 0, 0 },
1046 };
1047 
1048 static struct sony_nc_event sony_127_events[] = {
1049 	{ 0x81, SONYPI_EVENT_MODEKEY_PRESSED },
1050 	{ 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED },
1051 	{ 0x82, SONYPI_EVENT_PKEY_P1 },
1052 	{ 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED },
1053 	{ 0x83, SONYPI_EVENT_PKEY_P2 },
1054 	{ 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED },
1055 	{ 0x84, SONYPI_EVENT_PKEY_P3 },
1056 	{ 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED },
1057 	{ 0x85, SONYPI_EVENT_PKEY_P4 },
1058 	{ 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
1059 	{ 0x86, SONYPI_EVENT_PKEY_P5 },
1060 	{ 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
1061 	{ 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
1062 	{ 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
1063 	{ 0, 0 },
1064 };
1065 
1066 /*
1067  * ACPI callbacks
1068  */
sony_nc_notify(struct acpi_device * device,u32 event)1069 static void sony_nc_notify(struct acpi_device *device, u32 event)
1070 {
1071 	u32 ev = event;
1072 
1073 	if (ev >= 0x90) {
1074 		/* New-style event */
1075 		int result;
1076 		int key_handle = 0;
1077 		ev -= 0x90;
1078 
1079 		if (sony_find_snc_handle(0x100) == ev)
1080 			key_handle = 0x100;
1081 		if (sony_find_snc_handle(0x127) == ev)
1082 			key_handle = 0x127;
1083 
1084 		if (key_handle) {
1085 			struct sony_nc_event *key_event;
1086 
1087 			if (sony_call_snc_handle(key_handle, 0x200, &result)) {
1088 				dprintk("sony_nc_notify, unable to decode"
1089 					" event 0x%.2x 0x%.2x\n", key_handle,
1090 					ev);
1091 				/* restore the original event */
1092 				ev = event;
1093 			} else {
1094 				ev = result & 0xFF;
1095 
1096 				if (key_handle == 0x100)
1097 					key_event = sony_100_events;
1098 				else
1099 					key_event = sony_127_events;
1100 
1101 				for (; key_event->data; key_event++) {
1102 					if (key_event->data == ev) {
1103 						ev = key_event->event;
1104 						break;
1105 					}
1106 				}
1107 
1108 				if (!key_event->data)
1109 					pr_info("Unknown event: 0x%x 0x%x\n",
1110 						key_handle, ev);
1111 				else
1112 					sony_laptop_report_input_event(ev);
1113 			}
1114 		} else if (sony_find_snc_handle(sony_rfkill_handle) == ev) {
1115 			sony_nc_rfkill_update();
1116 			return;
1117 		}
1118 	} else
1119 		sony_laptop_report_input_event(ev);
1120 
1121 	dprintk("sony_nc_notify, event: 0x%.2x\n", ev);
1122 	acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
1123 }
1124 
sony_walk_callback(acpi_handle handle,u32 level,void * context,void ** return_value)1125 static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
1126 				      void *context, void **return_value)
1127 {
1128 	struct acpi_device_info *info;
1129 
1130 	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
1131 		pr_warn("method: name: %4.4s, args %X\n",
1132 			(char *)&info->name, info->param_count);
1133 
1134 		kfree(info);
1135 	}
1136 
1137 	return AE_OK;
1138 }
1139 
1140 /*
1141  * ACPI device
1142  */
sony_nc_function_setup(struct acpi_device * device)1143 static int sony_nc_function_setup(struct acpi_device *device)
1144 {
1145 	int result;
1146 
1147 	/* Enable all events */
1148 	acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
1149 
1150 	/* Setup hotkeys */
1151 	sony_call_snc_handle(0x0100, 0, &result);
1152 	sony_call_snc_handle(0x0101, 0, &result);
1153 	sony_call_snc_handle(0x0102, 0x100, &result);
1154 	sony_call_snc_handle(0x0127, 0, &result);
1155 
1156 	return 0;
1157 }
1158 
sony_nc_resume(struct acpi_device * device)1159 static int sony_nc_resume(struct acpi_device *device)
1160 {
1161 	struct sony_nc_value *item;
1162 	acpi_handle handle;
1163 
1164 	for (item = sony_nc_values; item->name; item++) {
1165 		int ret;
1166 
1167 		if (!item->valid)
1168 			continue;
1169 		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
1170 				       item->value, NULL);
1171 		if (ret < 0) {
1172 			pr_err("%s: %d\n", __func__, ret);
1173 			break;
1174 		}
1175 	}
1176 
1177 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
1178 					 &handle))) {
1179 		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
1180 			dprintk("ECON Method failed\n");
1181 	}
1182 
1183 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1184 					 &handle))) {
1185 		dprintk("Doing SNC setup\n");
1186 		sony_nc_function_setup(device);
1187 	}
1188 
1189 	/* re-read rfkill state */
1190 	sony_nc_rfkill_update();
1191 
1192 	/* restore kbd backlight states */
1193 	sony_nc_kbd_backlight_resume();
1194 
1195 	return 0;
1196 }
1197 
sony_nc_rfkill_cleanup(void)1198 static void sony_nc_rfkill_cleanup(void)
1199 {
1200 	int i;
1201 
1202 	for (i = 0; i < N_SONY_RFKILL; i++) {
1203 		if (sony_rfkill_devices[i]) {
1204 			rfkill_unregister(sony_rfkill_devices[i]);
1205 			rfkill_destroy(sony_rfkill_devices[i]);
1206 		}
1207 	}
1208 }
1209 
sony_nc_rfkill_set(void * data,bool blocked)1210 static int sony_nc_rfkill_set(void *data, bool blocked)
1211 {
1212 	int result;
1213 	int argument = sony_rfkill_address[(long) data] + 0x100;
1214 
1215 	if (!blocked)
1216 		argument |= 0xff0000;
1217 
1218 	return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1219 }
1220 
1221 static const struct rfkill_ops sony_rfkill_ops = {
1222 	.set_block = sony_nc_rfkill_set,
1223 };
1224 
sony_nc_setup_rfkill(struct acpi_device * device,enum sony_nc_rfkill nc_type)1225 static int sony_nc_setup_rfkill(struct acpi_device *device,
1226 				enum sony_nc_rfkill nc_type)
1227 {
1228 	int err = 0;
1229 	struct rfkill *rfk;
1230 	enum rfkill_type type;
1231 	const char *name;
1232 	int result;
1233 	bool hwblock;
1234 
1235 	switch (nc_type) {
1236 	case SONY_WIFI:
1237 		type = RFKILL_TYPE_WLAN;
1238 		name = "sony-wifi";
1239 		break;
1240 	case SONY_BLUETOOTH:
1241 		type = RFKILL_TYPE_BLUETOOTH;
1242 		name = "sony-bluetooth";
1243 		break;
1244 	case SONY_WWAN:
1245 		type = RFKILL_TYPE_WWAN;
1246 		name = "sony-wwan";
1247 		break;
1248 	case SONY_WIMAX:
1249 		type = RFKILL_TYPE_WIMAX;
1250 		name = "sony-wimax";
1251 		break;
1252 	default:
1253 		return -EINVAL;
1254 	}
1255 
1256 	rfk = rfkill_alloc(name, &device->dev, type,
1257 			   &sony_rfkill_ops, (void *)nc_type);
1258 	if (!rfk)
1259 		return -ENOMEM;
1260 
1261 	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1262 	hwblock = !(result & 0x1);
1263 	rfkill_set_hw_state(rfk, hwblock);
1264 
1265 	err = rfkill_register(rfk);
1266 	if (err) {
1267 		rfkill_destroy(rfk);
1268 		return err;
1269 	}
1270 	sony_rfkill_devices[nc_type] = rfk;
1271 	return err;
1272 }
1273 
sony_nc_rfkill_update(void)1274 static void sony_nc_rfkill_update(void)
1275 {
1276 	enum sony_nc_rfkill i;
1277 	int result;
1278 	bool hwblock;
1279 
1280 	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1281 	hwblock = !(result & 0x1);
1282 
1283 	for (i = 0; i < N_SONY_RFKILL; i++) {
1284 		int argument = sony_rfkill_address[i];
1285 
1286 		if (!sony_rfkill_devices[i])
1287 			continue;
1288 
1289 		if (hwblock) {
1290 			if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
1291 				/* we already know we're blocked */
1292 			}
1293 			continue;
1294 		}
1295 
1296 		sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1297 		rfkill_set_states(sony_rfkill_devices[i],
1298 				  !(result & 0xf), false);
1299 	}
1300 }
1301 
sony_nc_rfkill_setup(struct acpi_device * device)1302 static void sony_nc_rfkill_setup(struct acpi_device *device)
1303 {
1304 	int offset;
1305 	u8 dev_code, i;
1306 	acpi_status status;
1307 	struct acpi_object_list params;
1308 	union acpi_object in_obj;
1309 	union acpi_object *device_enum;
1310 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1311 
1312 	offset = sony_find_snc_handle(0x124);
1313 	if (offset == -1) {
1314 		offset = sony_find_snc_handle(0x135);
1315 		if (offset == -1)
1316 			return;
1317 		else
1318 			sony_rfkill_handle = 0x135;
1319 	} else
1320 		sony_rfkill_handle = 0x124;
1321 	dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
1322 
1323 	/* need to read the whole buffer returned by the acpi call to SN06
1324 	 * here otherwise we may miss some features
1325 	 */
1326 	params.count = 1;
1327 	params.pointer = &in_obj;
1328 	in_obj.type = ACPI_TYPE_INTEGER;
1329 	in_obj.integer.value = offset;
1330 	status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
1331 			&buffer);
1332 	if (ACPI_FAILURE(status)) {
1333 		dprintk("Radio device enumeration failed\n");
1334 		return;
1335 	}
1336 
1337 	device_enum = (union acpi_object *) buffer.pointer;
1338 	if (!device_enum) {
1339 		pr_err("No SN06 return object\n");
1340 		goto out_no_enum;
1341 	}
1342 	if (device_enum->type != ACPI_TYPE_BUFFER) {
1343 		pr_err("Invalid SN06 return object 0x%.2x\n",
1344 		       device_enum->type);
1345 		goto out_no_enum;
1346 	}
1347 
1348 	/* the buffer is filled with magic numbers describing the devices
1349 	 * available, 0xff terminates the enumeration
1350 	 */
1351 	for (i = 0; i < device_enum->buffer.length; i++) {
1352 
1353 		dev_code = *(device_enum->buffer.pointer + i);
1354 		if (dev_code == 0xff)
1355 			break;
1356 
1357 		dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
1358 
1359 		if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
1360 			sony_nc_setup_rfkill(device, SONY_WIFI);
1361 
1362 		if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
1363 			sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1364 
1365 		if ((0xf0 & dev_code) == 0x20 &&
1366 				!sony_rfkill_devices[SONY_WWAN])
1367 			sony_nc_setup_rfkill(device, SONY_WWAN);
1368 
1369 		if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
1370 			sony_nc_setup_rfkill(device, SONY_WIMAX);
1371 	}
1372 
1373 out_no_enum:
1374 	kfree(buffer.pointer);
1375 	return;
1376 }
1377 
1378 /* Keyboard backlight feature */
1379 #define KBDBL_HANDLER	0x137
1380 #define KBDBL_PRESENT	0xB00
1381 #define	SET_MODE	0xC00
1382 #define SET_STATE	0xD00
1383 #define SET_TIMEOUT	0xE00
1384 
1385 struct kbd_backlight {
1386 	int mode;
1387 	int timeout;
1388 	struct device_attribute mode_attr;
1389 	struct device_attribute timeout_attr;
1390 };
1391 
1392 static struct kbd_backlight *kbdbl_handle;
1393 
__sony_nc_kbd_backlight_mode_set(u8 value)1394 static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
1395 {
1396 	int result;
1397 
1398 	if (value > 1)
1399 		return -EINVAL;
1400 
1401 	if (sony_call_snc_handle(KBDBL_HANDLER,
1402 				(value << 0x10) | SET_MODE, &result))
1403 		return -EIO;
1404 
1405 	/* Try to turn the light on/off immediately */
1406 	sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE,
1407 			&result);
1408 
1409 	kbdbl_handle->mode = value;
1410 
1411 	return 0;
1412 }
1413 
sony_nc_kbd_backlight_mode_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)1414 static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
1415 		struct device_attribute *attr,
1416 		const char *buffer, size_t count)
1417 {
1418 	int ret = 0;
1419 	unsigned long value;
1420 
1421 	if (count > 31)
1422 		return -EINVAL;
1423 
1424 	if (strict_strtoul(buffer, 10, &value))
1425 		return -EINVAL;
1426 
1427 	ret = __sony_nc_kbd_backlight_mode_set(value);
1428 	if (ret < 0)
1429 		return ret;
1430 
1431 	return count;
1432 }
1433 
sony_nc_kbd_backlight_mode_show(struct device * dev,struct device_attribute * attr,char * buffer)1434 static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
1435 		struct device_attribute *attr, char *buffer)
1436 {
1437 	ssize_t count = 0;
1438 	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode);
1439 	return count;
1440 }
1441 
__sony_nc_kbd_backlight_timeout_set(u8 value)1442 static int __sony_nc_kbd_backlight_timeout_set(u8 value)
1443 {
1444 	int result;
1445 
1446 	if (value > 3)
1447 		return -EINVAL;
1448 
1449 	if (sony_call_snc_handle(KBDBL_HANDLER,
1450 				(value << 0x10) | SET_TIMEOUT, &result))
1451 		return -EIO;
1452 
1453 	kbdbl_handle->timeout = value;
1454 
1455 	return 0;
1456 }
1457 
sony_nc_kbd_backlight_timeout_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)1458 static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
1459 		struct device_attribute *attr,
1460 		const char *buffer, size_t count)
1461 {
1462 	int ret = 0;
1463 	unsigned long value;
1464 
1465 	if (count > 31)
1466 		return -EINVAL;
1467 
1468 	if (strict_strtoul(buffer, 10, &value))
1469 		return -EINVAL;
1470 
1471 	ret = __sony_nc_kbd_backlight_timeout_set(value);
1472 	if (ret < 0)
1473 		return ret;
1474 
1475 	return count;
1476 }
1477 
sony_nc_kbd_backlight_timeout_show(struct device * dev,struct device_attribute * attr,char * buffer)1478 static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
1479 		struct device_attribute *attr, char *buffer)
1480 {
1481 	ssize_t count = 0;
1482 	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout);
1483 	return count;
1484 }
1485 
sony_nc_kbd_backlight_setup(struct platform_device * pd)1486 static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
1487 {
1488 	int result;
1489 
1490 	if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
1491 		return 0;
1492 	if (!(result & 0x02))
1493 		return 0;
1494 
1495 	kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL);
1496 	if (!kbdbl_handle)
1497 		return -ENOMEM;
1498 
1499 	sysfs_attr_init(&kbdbl_handle->mode_attr.attr);
1500 	kbdbl_handle->mode_attr.attr.name = "kbd_backlight";
1501 	kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
1502 	kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show;
1503 	kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store;
1504 
1505 	sysfs_attr_init(&kbdbl_handle->timeout_attr.attr);
1506 	kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout";
1507 	kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
1508 	kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
1509 	kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
1510 
1511 	if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr))
1512 		goto outkzalloc;
1513 
1514 	if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr))
1515 		goto outmode;
1516 
1517 	__sony_nc_kbd_backlight_mode_set(kbd_backlight);
1518 	__sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
1519 
1520 	return 0;
1521 
1522 outmode:
1523 	device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
1524 outkzalloc:
1525 	kfree(kbdbl_handle);
1526 	kbdbl_handle = NULL;
1527 	return -1;
1528 }
1529 
sony_nc_kbd_backlight_cleanup(struct platform_device * pd)1530 static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
1531 {
1532 	if (kbdbl_handle) {
1533 		int result;
1534 
1535 		device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
1536 		device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
1537 
1538 		/* restore the default hw behaviour */
1539 		sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result);
1540 		sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result);
1541 
1542 		kfree(kbdbl_handle);
1543 	}
1544 	return 0;
1545 }
1546 
sony_nc_kbd_backlight_resume(void)1547 static void sony_nc_kbd_backlight_resume(void)
1548 {
1549 	int ignore = 0;
1550 
1551 	if (!kbdbl_handle)
1552 		return;
1553 
1554 	if (kbdbl_handle->mode == 0)
1555 		sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore);
1556 
1557 	if (kbdbl_handle->timeout != 0)
1558 		sony_call_snc_handle(KBDBL_HANDLER,
1559 				(kbdbl_handle->timeout << 0x10) | SET_TIMEOUT,
1560 				&ignore);
1561 }
1562 
sony_nc_backlight_ng_read_limits(int handle,struct sony_backlight_props * props)1563 static void sony_nc_backlight_ng_read_limits(int handle,
1564 		struct sony_backlight_props *props)
1565 {
1566 	int offset;
1567 	acpi_status status;
1568 	u8 brlvl, i;
1569 	u8 min = 0xff, max = 0x00;
1570 	struct acpi_object_list params;
1571 	union acpi_object in_obj;
1572 	union acpi_object *lvl_enum;
1573 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1574 
1575 	props->handle = handle;
1576 	props->offset = 0;
1577 	props->maxlvl = 0xff;
1578 
1579 	offset = sony_find_snc_handle(handle);
1580 	if (offset < 0)
1581 		return;
1582 
1583 	/* try to read the boundaries from ACPI tables, if we fail the above
1584 	 * defaults should be reasonable
1585 	 */
1586 	params.count = 1;
1587 	params.pointer = &in_obj;
1588 	in_obj.type = ACPI_TYPE_INTEGER;
1589 	in_obj.integer.value = offset;
1590 	status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
1591 			&buffer);
1592 	if (ACPI_FAILURE(status))
1593 		return;
1594 
1595 	lvl_enum = (union acpi_object *) buffer.pointer;
1596 	if (!lvl_enum) {
1597 		pr_err("No SN06 return object.");
1598 		return;
1599 	}
1600 	if (lvl_enum->type != ACPI_TYPE_BUFFER) {
1601 		pr_err("Invalid SN06 return object 0x%.2x\n",
1602 		       lvl_enum->type);
1603 		goto out_invalid;
1604 	}
1605 
1606 	/* the buffer lists brightness levels available, brightness levels are
1607 	 * from 0 to 8 in the array, other values are used by ALS control.
1608 	 */
1609 	for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) {
1610 
1611 		brlvl = *(lvl_enum->buffer.pointer + i);
1612 		dprintk("Brightness level: %d\n", brlvl);
1613 
1614 		if (!brlvl)
1615 			break;
1616 
1617 		if (brlvl > max)
1618 			max = brlvl;
1619 		if (brlvl < min)
1620 			min = brlvl;
1621 	}
1622 	props->offset = min;
1623 	props->maxlvl = max;
1624 	dprintk("Brightness levels: min=%d max=%d\n", props->offset,
1625 			props->maxlvl);
1626 
1627 out_invalid:
1628 	kfree(buffer.pointer);
1629 	return;
1630 }
1631 
sony_nc_backlight_setup(void)1632 static void sony_nc_backlight_setup(void)
1633 {
1634 	acpi_handle unused;
1635 	int max_brightness = 0;
1636 	const struct backlight_ops *ops = NULL;
1637 	struct backlight_properties props;
1638 
1639 	if (sony_find_snc_handle(0x12f) != -1) {
1640 		ops = &sony_backlight_ng_ops;
1641 		sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
1642 		max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
1643 
1644 	} else if (sony_find_snc_handle(0x137) != -1) {
1645 		ops = &sony_backlight_ng_ops;
1646 		sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
1647 		max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
1648 
1649 	} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
1650 						&unused))) {
1651 		ops = &sony_backlight_ops;
1652 		max_brightness = SONY_MAX_BRIGHTNESS - 1;
1653 
1654 	} else
1655 		return;
1656 
1657 	memset(&props, 0, sizeof(struct backlight_properties));
1658 	props.type = BACKLIGHT_PLATFORM;
1659 	props.max_brightness = max_brightness;
1660 	sony_bl_props.dev = backlight_device_register("sony", NULL,
1661 						      &sony_bl_props,
1662 						      ops, &props);
1663 
1664 	if (IS_ERR(sony_bl_props.dev)) {
1665 		pr_warn("unable to register backlight device\n");
1666 		sony_bl_props.dev = NULL;
1667 	} else
1668 		sony_bl_props.dev->props.brightness =
1669 			ops->get_brightness(sony_bl_props.dev);
1670 }
1671 
sony_nc_backlight_cleanup(void)1672 static void sony_nc_backlight_cleanup(void)
1673 {
1674 	if (sony_bl_props.dev)
1675 		backlight_device_unregister(sony_bl_props.dev);
1676 }
1677 
sony_nc_add(struct acpi_device * device)1678 static int sony_nc_add(struct acpi_device *device)
1679 {
1680 	acpi_status status;
1681 	int result = 0;
1682 	acpi_handle handle;
1683 	struct sony_nc_value *item;
1684 
1685 	pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
1686 
1687 	sony_nc_acpi_device = device;
1688 	strcpy(acpi_device_class(device), "sony/hotkey");
1689 
1690 	sony_nc_acpi_handle = device->handle;
1691 
1692 	/* read device status */
1693 	result = acpi_bus_get_status(device);
1694 	/* bail IFF the above call was successful and the device is not present */
1695 	if (!result && !device->status.present) {
1696 		dprintk("Device not present\n");
1697 		result = -ENODEV;
1698 		goto outwalk;
1699 	}
1700 
1701 	result = sony_pf_add();
1702 	if (result)
1703 		goto outpresent;
1704 
1705 	if (debug) {
1706 		status = acpi_walk_namespace(ACPI_TYPE_METHOD,
1707 				sony_nc_acpi_handle, 1, sony_walk_callback,
1708 				NULL, NULL, NULL);
1709 		if (ACPI_FAILURE(status)) {
1710 			pr_warn("unable to walk acpi resources\n");
1711 			result = -ENODEV;
1712 			goto outpresent;
1713 		}
1714 	}
1715 
1716 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
1717 					 &handle))) {
1718 		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
1719 			dprintk("ECON Method failed\n");
1720 	}
1721 
1722 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1723 					 &handle))) {
1724 		dprintk("Doing SNC setup\n");
1725 		result = sony_nc_handles_setup(sony_pf_device);
1726 		if (result)
1727 			goto outpresent;
1728 		result = sony_nc_kbd_backlight_setup(sony_pf_device);
1729 		if (result)
1730 			goto outsnc;
1731 		sony_nc_function_setup(device);
1732 		sony_nc_rfkill_setup(device);
1733 	}
1734 
1735 	/* setup input devices and helper fifo */
1736 	result = sony_laptop_setup_input(device);
1737 	if (result) {
1738 		pr_err("Unable to create input devices\n");
1739 		goto outkbdbacklight;
1740 	}
1741 
1742 	if (acpi_video_backlight_support()) {
1743 		pr_info("brightness ignored, must be controlled by ACPI video driver\n");
1744 	} else {
1745 		sony_nc_backlight_setup();
1746 	}
1747 
1748 	/* create sony_pf sysfs attributes related to the SNC device */
1749 	for (item = sony_nc_values; item->name; ++item) {
1750 
1751 		if (!debug && item->debug)
1752 			continue;
1753 
1754 		/* find the available acpiget as described in the DSDT */
1755 		for (; item->acpiget && *item->acpiget; ++item->acpiget) {
1756 			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
1757 							 *item->acpiget,
1758 							 &handle))) {
1759 				dprintk("Found %s getter: %s\n",
1760 						item->name, *item->acpiget);
1761 				item->devattr.attr.mode |= S_IRUGO;
1762 				break;
1763 			}
1764 		}
1765 
1766 		/* find the available acpiset as described in the DSDT */
1767 		for (; item->acpiset && *item->acpiset; ++item->acpiset) {
1768 			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
1769 							 *item->acpiset,
1770 							 &handle))) {
1771 				dprintk("Found %s setter: %s\n",
1772 						item->name, *item->acpiset);
1773 				item->devattr.attr.mode |= S_IWUSR;
1774 				break;
1775 			}
1776 		}
1777 
1778 		if (item->devattr.attr.mode != 0) {
1779 			result =
1780 			    device_create_file(&sony_pf_device->dev,
1781 					       &item->devattr);
1782 			if (result)
1783 				goto out_sysfs;
1784 		}
1785 	}
1786 
1787 	return 0;
1788 
1789       out_sysfs:
1790 	for (item = sony_nc_values; item->name; ++item) {
1791 		device_remove_file(&sony_pf_device->dev, &item->devattr);
1792 	}
1793 	sony_nc_backlight_cleanup();
1794 
1795 	sony_laptop_remove_input();
1796 
1797       outkbdbacklight:
1798 	sony_nc_kbd_backlight_cleanup(sony_pf_device);
1799 
1800       outsnc:
1801 	sony_nc_handles_cleanup(sony_pf_device);
1802 
1803       outpresent:
1804 	sony_pf_remove();
1805 
1806       outwalk:
1807 	sony_nc_rfkill_cleanup();
1808 	return result;
1809 }
1810 
sony_nc_remove(struct acpi_device * device,int type)1811 static int sony_nc_remove(struct acpi_device *device, int type)
1812 {
1813 	struct sony_nc_value *item;
1814 
1815 	sony_nc_backlight_cleanup();
1816 
1817 	sony_nc_acpi_device = NULL;
1818 
1819 	for (item = sony_nc_values; item->name; ++item) {
1820 		device_remove_file(&sony_pf_device->dev, &item->devattr);
1821 	}
1822 
1823 	sony_nc_kbd_backlight_cleanup(sony_pf_device);
1824 	sony_nc_handles_cleanup(sony_pf_device);
1825 	sony_pf_remove();
1826 	sony_laptop_remove_input();
1827 	sony_nc_rfkill_cleanup();
1828 	dprintk(SONY_NC_DRIVER_NAME " removed.\n");
1829 
1830 	return 0;
1831 }
1832 
1833 static const struct acpi_device_id sony_device_ids[] = {
1834 	{SONY_NC_HID, 0},
1835 	{SONY_PIC_HID, 0},
1836 	{"", 0},
1837 };
1838 MODULE_DEVICE_TABLE(acpi, sony_device_ids);
1839 
1840 static const struct acpi_device_id sony_nc_device_ids[] = {
1841 	{SONY_NC_HID, 0},
1842 	{"", 0},
1843 };
1844 
1845 static struct acpi_driver sony_nc_driver = {
1846 	.name = SONY_NC_DRIVER_NAME,
1847 	.class = SONY_NC_CLASS,
1848 	.ids = sony_nc_device_ids,
1849 	.owner = THIS_MODULE,
1850 	.ops = {
1851 		.add = sony_nc_add,
1852 		.remove = sony_nc_remove,
1853 		.resume = sony_nc_resume,
1854 		.notify = sony_nc_notify,
1855 		},
1856 };
1857 
1858 /*********** SPIC (SNY6001) Device ***********/
1859 
1860 #define SONYPI_DEVICE_TYPE1	0x00000001
1861 #define SONYPI_DEVICE_TYPE2	0x00000002
1862 #define SONYPI_DEVICE_TYPE3	0x00000004
1863 
1864 #define SONYPI_TYPE1_OFFSET	0x04
1865 #define SONYPI_TYPE2_OFFSET	0x12
1866 #define SONYPI_TYPE3_OFFSET	0x12
1867 
1868 struct sony_pic_ioport {
1869 	struct acpi_resource_io	io1;
1870 	struct acpi_resource_io	io2;
1871 	struct list_head	list;
1872 };
1873 
1874 struct sony_pic_irq {
1875 	struct acpi_resource_irq	irq;
1876 	struct list_head		list;
1877 };
1878 
1879 struct sonypi_eventtypes {
1880 	u8			data;
1881 	unsigned long		mask;
1882 	struct sonypi_event	*events;
1883 };
1884 
1885 struct sony_pic_dev {
1886 	struct acpi_device		*acpi_dev;
1887 	struct sony_pic_irq		*cur_irq;
1888 	struct sony_pic_ioport		*cur_ioport;
1889 	struct list_head		interrupts;
1890 	struct list_head		ioports;
1891 	struct mutex			lock;
1892 	struct sonypi_eventtypes	*event_types;
1893 	int                             (*handle_irq)(const u8, const u8);
1894 	int				model;
1895 	u16				evport_offset;
1896 	u8				camera_power;
1897 	u8				bluetooth_power;
1898 	u8				wwan_power;
1899 };
1900 
1901 static struct sony_pic_dev spic_dev = {
1902 	.interrupts	= LIST_HEAD_INIT(spic_dev.interrupts),
1903 	.ioports	= LIST_HEAD_INIT(spic_dev.ioports),
1904 };
1905 
1906 static int spic_drv_registered;
1907 
1908 /* Event masks */
1909 #define SONYPI_JOGGER_MASK			0x00000001
1910 #define SONYPI_CAPTURE_MASK			0x00000002
1911 #define SONYPI_FNKEY_MASK			0x00000004
1912 #define SONYPI_BLUETOOTH_MASK			0x00000008
1913 #define SONYPI_PKEY_MASK			0x00000010
1914 #define SONYPI_BACK_MASK			0x00000020
1915 #define SONYPI_HELP_MASK			0x00000040
1916 #define SONYPI_LID_MASK				0x00000080
1917 #define SONYPI_ZOOM_MASK			0x00000100
1918 #define SONYPI_THUMBPHRASE_MASK			0x00000200
1919 #define SONYPI_MEYE_MASK			0x00000400
1920 #define SONYPI_MEMORYSTICK_MASK			0x00000800
1921 #define SONYPI_BATTERY_MASK			0x00001000
1922 #define SONYPI_WIRELESS_MASK			0x00002000
1923 
1924 struct sonypi_event {
1925 	u8	data;
1926 	u8	event;
1927 };
1928 
1929 /* The set of possible button release events */
1930 static struct sonypi_event sonypi_releaseev[] = {
1931 	{ 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED },
1932 	{ 0, 0 }
1933 };
1934 
1935 /* The set of possible jogger events  */
1936 static struct sonypi_event sonypi_joggerev[] = {
1937 	{ 0x1f, SONYPI_EVENT_JOGDIAL_UP },
1938 	{ 0x01, SONYPI_EVENT_JOGDIAL_DOWN },
1939 	{ 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED },
1940 	{ 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED },
1941 	{ 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP },
1942 	{ 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN },
1943 	{ 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED },
1944 	{ 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED },
1945 	{ 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP },
1946 	{ 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN },
1947 	{ 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED },
1948 	{ 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED },
1949 	{ 0x40, SONYPI_EVENT_JOGDIAL_PRESSED },
1950 	{ 0, 0 }
1951 };
1952 
1953 /* The set of possible capture button events */
1954 static struct sonypi_event sonypi_captureev[] = {
1955 	{ 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
1956 	{ 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
1957 	{ 0x40, SONYPI_EVENT_CAPTURE_PRESSED },
1958 	{ 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
1959 	{ 0, 0 }
1960 };
1961 
1962 /* The set of possible fnkeys events */
1963 static struct sonypi_event sonypi_fnkeyev[] = {
1964 	{ 0x10, SONYPI_EVENT_FNKEY_ESC },
1965 	{ 0x11, SONYPI_EVENT_FNKEY_F1 },
1966 	{ 0x12, SONYPI_EVENT_FNKEY_F2 },
1967 	{ 0x13, SONYPI_EVENT_FNKEY_F3 },
1968 	{ 0x14, SONYPI_EVENT_FNKEY_F4 },
1969 	{ 0x15, SONYPI_EVENT_FNKEY_F5 },
1970 	{ 0x16, SONYPI_EVENT_FNKEY_F6 },
1971 	{ 0x17, SONYPI_EVENT_FNKEY_F7 },
1972 	{ 0x18, SONYPI_EVENT_FNKEY_F8 },
1973 	{ 0x19, SONYPI_EVENT_FNKEY_F9 },
1974 	{ 0x1a, SONYPI_EVENT_FNKEY_F10 },
1975 	{ 0x1b, SONYPI_EVENT_FNKEY_F11 },
1976 	{ 0x1c, SONYPI_EVENT_FNKEY_F12 },
1977 	{ 0x1f, SONYPI_EVENT_FNKEY_RELEASED },
1978 	{ 0x21, SONYPI_EVENT_FNKEY_1 },
1979 	{ 0x22, SONYPI_EVENT_FNKEY_2 },
1980 	{ 0x31, SONYPI_EVENT_FNKEY_D },
1981 	{ 0x32, SONYPI_EVENT_FNKEY_E },
1982 	{ 0x33, SONYPI_EVENT_FNKEY_F },
1983 	{ 0x34, SONYPI_EVENT_FNKEY_S },
1984 	{ 0x35, SONYPI_EVENT_FNKEY_B },
1985 	{ 0x36, SONYPI_EVENT_FNKEY_ONLY },
1986 	{ 0, 0 }
1987 };
1988 
1989 /* The set of possible program key events */
1990 static struct sonypi_event sonypi_pkeyev[] = {
1991 	{ 0x01, SONYPI_EVENT_PKEY_P1 },
1992 	{ 0x02, SONYPI_EVENT_PKEY_P2 },
1993 	{ 0x04, SONYPI_EVENT_PKEY_P3 },
1994 	{ 0x20, SONYPI_EVENT_PKEY_P1 },
1995 	{ 0, 0 }
1996 };
1997 
1998 /* The set of possible bluetooth events */
1999 static struct sonypi_event sonypi_blueev[] = {
2000 	{ 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
2001 	{ 0x59, SONYPI_EVENT_BLUETOOTH_ON },
2002 	{ 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
2003 	{ 0, 0 }
2004 };
2005 
2006 /* The set of possible wireless events */
2007 static struct sonypi_event sonypi_wlessev[] = {
2008 	{ 0x59, SONYPI_EVENT_IGNORE },
2009 	{ 0x5a, SONYPI_EVENT_IGNORE },
2010 	{ 0, 0 }
2011 };
2012 
2013 /* The set of possible back button events */
2014 static struct sonypi_event sonypi_backev[] = {
2015 	{ 0x20, SONYPI_EVENT_BACK_PRESSED },
2016 	{ 0, 0 }
2017 };
2018 
2019 /* The set of possible help button events */
2020 static struct sonypi_event sonypi_helpev[] = {
2021 	{ 0x3b, SONYPI_EVENT_HELP_PRESSED },
2022 	{ 0, 0 }
2023 };
2024 
2025 
2026 /* The set of possible lid events */
2027 static struct sonypi_event sonypi_lidev[] = {
2028 	{ 0x51, SONYPI_EVENT_LID_CLOSED },
2029 	{ 0x50, SONYPI_EVENT_LID_OPENED },
2030 	{ 0, 0 }
2031 };
2032 
2033 /* The set of possible zoom events */
2034 static struct sonypi_event sonypi_zoomev[] = {
2035 	{ 0x39, SONYPI_EVENT_ZOOM_PRESSED },
2036 	{ 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED },
2037 	{ 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED },
2038 	{ 0x04, SONYPI_EVENT_ZOOM_PRESSED },
2039 	{ 0, 0 }
2040 };
2041 
2042 /* The set of possible thumbphrase events */
2043 static struct sonypi_event sonypi_thumbphraseev[] = {
2044 	{ 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED },
2045 	{ 0, 0 }
2046 };
2047 
2048 /* The set of possible motioneye camera events */
2049 static struct sonypi_event sonypi_meyeev[] = {
2050 	{ 0x00, SONYPI_EVENT_MEYE_FACE },
2051 	{ 0x01, SONYPI_EVENT_MEYE_OPPOSITE },
2052 	{ 0, 0 }
2053 };
2054 
2055 /* The set of possible memorystick events */
2056 static struct sonypi_event sonypi_memorystickev[] = {
2057 	{ 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT },
2058 	{ 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT },
2059 	{ 0, 0 }
2060 };
2061 
2062 /* The set of possible battery events */
2063 static struct sonypi_event sonypi_batteryev[] = {
2064 	{ 0x20, SONYPI_EVENT_BATTERY_INSERT },
2065 	{ 0x30, SONYPI_EVENT_BATTERY_REMOVE },
2066 	{ 0, 0 }
2067 };
2068 
2069 /* The set of possible volume events */
2070 static struct sonypi_event sonypi_volumeev[] = {
2071 	{ 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED },
2072 	{ 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED },
2073 	{ 0, 0 }
2074 };
2075 
2076 /* The set of possible brightness events */
2077 static struct sonypi_event sonypi_brightnessev[] = {
2078 	{ 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED },
2079 	{ 0, 0 }
2080 };
2081 
2082 static struct sonypi_eventtypes type1_events[] = {
2083 	{ 0, 0xffffffff, sonypi_releaseev },
2084 	{ 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
2085 	{ 0x30, SONYPI_LID_MASK, sonypi_lidev },
2086 	{ 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
2087 	{ 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
2088 	{ 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
2089 	{ 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
2090 	{ 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
2091 	{ 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
2092 	{ 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
2093 	{ 0 },
2094 };
2095 static struct sonypi_eventtypes type2_events[] = {
2096 	{ 0, 0xffffffff, sonypi_releaseev },
2097 	{ 0x38, SONYPI_LID_MASK, sonypi_lidev },
2098 	{ 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
2099 	{ 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
2100 	{ 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
2101 	{ 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
2102 	{ 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
2103 	{ 0x11, SONYPI_BACK_MASK, sonypi_backev },
2104 	{ 0x21, SONYPI_HELP_MASK, sonypi_helpev },
2105 	{ 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
2106 	{ 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
2107 	{ 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
2108 	{ 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
2109 	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
2110 	{ 0 },
2111 };
2112 static struct sonypi_eventtypes type3_events[] = {
2113 	{ 0, 0xffffffff, sonypi_releaseev },
2114 	{ 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
2115 	{ 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
2116 	{ 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
2117 	{ 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
2118 	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
2119 	{ 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev },
2120 	{ 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev },
2121 	{ 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev },
2122 	{ 0x05, SONYPI_PKEY_MASK, sonypi_volumeev },
2123 	{ 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev },
2124 	{ 0 },
2125 };
2126 
2127 /* low level spic calls */
2128 #define ITERATIONS_LONG		10000
2129 #define ITERATIONS_SHORT	10
2130 #define wait_on_command(command, iterations) {				\
2131 	unsigned int n = iterations;					\
2132 	while (--n && (command))					\
2133 		udelay(1);						\
2134 	if (!n)								\
2135 		dprintk("command failed at %s : %s (line %d)\n",	\
2136 				__FILE__, __func__, __LINE__);	\
2137 }
2138 
sony_pic_call1(u8 dev)2139 static u8 sony_pic_call1(u8 dev)
2140 {
2141 	u8 v1, v2;
2142 
2143 	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
2144 			ITERATIONS_LONG);
2145 	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
2146 	v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
2147 	v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
2148 	dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1);
2149 	return v2;
2150 }
2151 
sony_pic_call2(u8 dev,u8 fn)2152 static u8 sony_pic_call2(u8 dev, u8 fn)
2153 {
2154 	u8 v1;
2155 
2156 	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
2157 			ITERATIONS_LONG);
2158 	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
2159 	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
2160 			ITERATIONS_LONG);
2161 	outb(fn, spic_dev.cur_ioport->io1.minimum);
2162 	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
2163 	dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1);
2164 	return v1;
2165 }
2166 
sony_pic_call3(u8 dev,u8 fn,u8 v)2167 static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
2168 {
2169 	u8 v1;
2170 
2171 	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
2172 	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
2173 	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
2174 	outb(fn, spic_dev.cur_ioport->io1.minimum);
2175 	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
2176 	outb(v, spic_dev.cur_ioport->io1.minimum);
2177 	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
2178 	dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
2179 			dev, fn, v, v1);
2180 	return v1;
2181 }
2182 
2183 /*
2184  * minidrivers for SPIC models
2185  */
type3_handle_irq(const u8 data_mask,const u8 ev)2186 static int type3_handle_irq(const u8 data_mask, const u8 ev)
2187 {
2188 	/*
2189 	 * 0x31 could mean we have to take some extra action and wait for
2190 	 * the next irq for some Type3 models, it will generate a new
2191 	 * irq and we can read new data from the device:
2192 	 *  - 0x5c and 0x5f requires 0xA0
2193 	 *  - 0x61 requires 0xB3
2194 	 */
2195 	if (data_mask == 0x31) {
2196 		if (ev == 0x5c || ev == 0x5f)
2197 			sony_pic_call1(0xA0);
2198 		else if (ev == 0x61)
2199 			sony_pic_call1(0xB3);
2200 		return 0;
2201 	}
2202 	return 1;
2203 }
2204 
sony_pic_detect_device_type(struct sony_pic_dev * dev)2205 static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
2206 {
2207 	struct pci_dev *pcidev;
2208 
2209 	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
2210 			PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
2211 	if (pcidev) {
2212 		dev->model = SONYPI_DEVICE_TYPE1;
2213 		dev->evport_offset = SONYPI_TYPE1_OFFSET;
2214 		dev->event_types = type1_events;
2215 		goto out;
2216 	}
2217 
2218 	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
2219 			PCI_DEVICE_ID_INTEL_ICH6_1, NULL);
2220 	if (pcidev) {
2221 		dev->model = SONYPI_DEVICE_TYPE2;
2222 		dev->evport_offset = SONYPI_TYPE2_OFFSET;
2223 		dev->event_types = type2_events;
2224 		goto out;
2225 	}
2226 
2227 	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
2228 			PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
2229 	if (pcidev) {
2230 		dev->model = SONYPI_DEVICE_TYPE3;
2231 		dev->handle_irq = type3_handle_irq;
2232 		dev->evport_offset = SONYPI_TYPE3_OFFSET;
2233 		dev->event_types = type3_events;
2234 		goto out;
2235 	}
2236 
2237 	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
2238 			PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
2239 	if (pcidev) {
2240 		dev->model = SONYPI_DEVICE_TYPE3;
2241 		dev->handle_irq = type3_handle_irq;
2242 		dev->evport_offset = SONYPI_TYPE3_OFFSET;
2243 		dev->event_types = type3_events;
2244 		goto out;
2245 	}
2246 
2247 	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
2248 			PCI_DEVICE_ID_INTEL_ICH9_1, NULL);
2249 	if (pcidev) {
2250 		dev->model = SONYPI_DEVICE_TYPE3;
2251 		dev->handle_irq = type3_handle_irq;
2252 		dev->evport_offset = SONYPI_TYPE3_OFFSET;
2253 		dev->event_types = type3_events;
2254 		goto out;
2255 	}
2256 
2257 	/* default */
2258 	dev->model = SONYPI_DEVICE_TYPE2;
2259 	dev->evport_offset = SONYPI_TYPE2_OFFSET;
2260 	dev->event_types = type2_events;
2261 
2262 out:
2263 	if (pcidev)
2264 		pci_dev_put(pcidev);
2265 
2266 	pr_info("detected Type%d model\n",
2267 		dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
2268 		dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
2269 }
2270 
2271 /* camera tests and poweron/poweroff */
2272 #define SONYPI_CAMERA_PICTURE		5
2273 #define SONYPI_CAMERA_CONTROL		0x10
2274 
2275 #define SONYPI_CAMERA_BRIGHTNESS		0
2276 #define SONYPI_CAMERA_CONTRAST			1
2277 #define SONYPI_CAMERA_HUE			2
2278 #define SONYPI_CAMERA_COLOR			3
2279 #define SONYPI_CAMERA_SHARPNESS			4
2280 
2281 #define SONYPI_CAMERA_EXPOSURE_MASK		0xC
2282 #define SONYPI_CAMERA_WHITE_BALANCE_MASK	0x3
2283 #define SONYPI_CAMERA_PICTURE_MODE_MASK		0x30
2284 #define SONYPI_CAMERA_MUTE_MASK			0x40
2285 
2286 /* the rest don't need a loop until not 0xff */
2287 #define SONYPI_CAMERA_AGC			6
2288 #define SONYPI_CAMERA_AGC_MASK			0x30
2289 #define SONYPI_CAMERA_SHUTTER_MASK 		0x7
2290 
2291 #define SONYPI_CAMERA_SHUTDOWN_REQUEST		7
2292 #define SONYPI_CAMERA_CONTROL			0x10
2293 
2294 #define SONYPI_CAMERA_STATUS 			7
2295 #define SONYPI_CAMERA_STATUS_READY 		0x2
2296 #define SONYPI_CAMERA_STATUS_POSITION		0x4
2297 
2298 #define SONYPI_DIRECTION_BACKWARDS 		0x4
2299 
2300 #define SONYPI_CAMERA_REVISION 			8
2301 #define SONYPI_CAMERA_ROMVERSION 		9
2302 
__sony_pic_camera_ready(void)2303 static int __sony_pic_camera_ready(void)
2304 {
2305 	u8 v;
2306 
2307 	v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
2308 	return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
2309 }
2310 
__sony_pic_camera_off(void)2311 static int __sony_pic_camera_off(void)
2312 {
2313 	if (!camera) {
2314 		pr_warn("camera control not enabled\n");
2315 		return -ENODEV;
2316 	}
2317 
2318 	wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
2319 				SONYPI_CAMERA_MUTE_MASK),
2320 			ITERATIONS_SHORT);
2321 
2322 	if (spic_dev.camera_power) {
2323 		sony_pic_call2(0x91, 0);
2324 		spic_dev.camera_power = 0;
2325 	}
2326 	return 0;
2327 }
2328 
__sony_pic_camera_on(void)2329 static int __sony_pic_camera_on(void)
2330 {
2331 	int i, j, x;
2332 
2333 	if (!camera) {
2334 		pr_warn("camera control not enabled\n");
2335 		return -ENODEV;
2336 	}
2337 
2338 	if (spic_dev.camera_power)
2339 		return 0;
2340 
2341 	for (j = 5; j > 0; j--) {
2342 
2343 		for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
2344 			msleep(10);
2345 		sony_pic_call1(0x93);
2346 
2347 		for (i = 400; i > 0; i--) {
2348 			if (__sony_pic_camera_ready())
2349 				break;
2350 			msleep(10);
2351 		}
2352 		if (i)
2353 			break;
2354 	}
2355 
2356 	if (j == 0) {
2357 		pr_warn("failed to power on camera\n");
2358 		return -ENODEV;
2359 	}
2360 
2361 	wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL,
2362 				0x5a),
2363 			ITERATIONS_SHORT);
2364 
2365 	spic_dev.camera_power = 1;
2366 	return 0;
2367 }
2368 
2369 /* External camera command (exported to the motion eye v4l driver) */
sony_pic_camera_command(int command,u8 value)2370 int sony_pic_camera_command(int command, u8 value)
2371 {
2372 	if (!camera)
2373 		return -EIO;
2374 
2375 	mutex_lock(&spic_dev.lock);
2376 
2377 	switch (command) {
2378 	case SONY_PIC_COMMAND_SETCAMERA:
2379 		if (value)
2380 			__sony_pic_camera_on();
2381 		else
2382 			__sony_pic_camera_off();
2383 		break;
2384 	case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
2385 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value),
2386 				ITERATIONS_SHORT);
2387 		break;
2388 	case SONY_PIC_COMMAND_SETCAMERACONTRAST:
2389 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
2390 				ITERATIONS_SHORT);
2391 		break;
2392 	case SONY_PIC_COMMAND_SETCAMERAHUE:
2393 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
2394 				ITERATIONS_SHORT);
2395 		break;
2396 	case SONY_PIC_COMMAND_SETCAMERACOLOR:
2397 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
2398 				ITERATIONS_SHORT);
2399 		break;
2400 	case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
2401 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
2402 				ITERATIONS_SHORT);
2403 		break;
2404 	case SONY_PIC_COMMAND_SETCAMERAPICTURE:
2405 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
2406 				ITERATIONS_SHORT);
2407 		break;
2408 	case SONY_PIC_COMMAND_SETCAMERAAGC:
2409 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
2410 				ITERATIONS_SHORT);
2411 		break;
2412 	default:
2413 		pr_err("sony_pic_camera_command invalid: %d\n", command);
2414 		break;
2415 	}
2416 	mutex_unlock(&spic_dev.lock);
2417 	return 0;
2418 }
2419 EXPORT_SYMBOL(sony_pic_camera_command);
2420 
2421 /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */
__sony_pic_set_wwanpower(u8 state)2422 static void __sony_pic_set_wwanpower(u8 state)
2423 {
2424 	state = !!state;
2425 	if (spic_dev.wwan_power == state)
2426 		return;
2427 	sony_pic_call2(0xB0, state);
2428 	sony_pic_call1(0x82);
2429 	spic_dev.wwan_power = state;
2430 }
2431 
sony_pic_wwanpower_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)2432 static ssize_t sony_pic_wwanpower_store(struct device *dev,
2433 		struct device_attribute *attr,
2434 		const char *buffer, size_t count)
2435 {
2436 	unsigned long value;
2437 	if (count > 31)
2438 		return -EINVAL;
2439 
2440 	value = simple_strtoul(buffer, NULL, 10);
2441 	mutex_lock(&spic_dev.lock);
2442 	__sony_pic_set_wwanpower(value);
2443 	mutex_unlock(&spic_dev.lock);
2444 
2445 	return count;
2446 }
2447 
sony_pic_wwanpower_show(struct device * dev,struct device_attribute * attr,char * buffer)2448 static ssize_t sony_pic_wwanpower_show(struct device *dev,
2449 		struct device_attribute *attr, char *buffer)
2450 {
2451 	ssize_t count;
2452 	mutex_lock(&spic_dev.lock);
2453 	count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.wwan_power);
2454 	mutex_unlock(&spic_dev.lock);
2455 	return count;
2456 }
2457 
2458 /* bluetooth subsystem power state */
__sony_pic_set_bluetoothpower(u8 state)2459 static void __sony_pic_set_bluetoothpower(u8 state)
2460 {
2461 	state = !!state;
2462 	if (spic_dev.bluetooth_power == state)
2463 		return;
2464 	sony_pic_call2(0x96, state);
2465 	sony_pic_call1(0x82);
2466 	spic_dev.bluetooth_power = state;
2467 }
2468 
sony_pic_bluetoothpower_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)2469 static ssize_t sony_pic_bluetoothpower_store(struct device *dev,
2470 		struct device_attribute *attr,
2471 		const char *buffer, size_t count)
2472 {
2473 	unsigned long value;
2474 	if (count > 31)
2475 		return -EINVAL;
2476 
2477 	value = simple_strtoul(buffer, NULL, 10);
2478 	mutex_lock(&spic_dev.lock);
2479 	__sony_pic_set_bluetoothpower(value);
2480 	mutex_unlock(&spic_dev.lock);
2481 
2482 	return count;
2483 }
2484 
sony_pic_bluetoothpower_show(struct device * dev,struct device_attribute * attr,char * buffer)2485 static ssize_t sony_pic_bluetoothpower_show(struct device *dev,
2486 		struct device_attribute *attr, char *buffer)
2487 {
2488 	ssize_t count = 0;
2489 	mutex_lock(&spic_dev.lock);
2490 	count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power);
2491 	mutex_unlock(&spic_dev.lock);
2492 	return count;
2493 }
2494 
2495 /* fan speed */
2496 /* FAN0 information (reverse engineered from ACPI tables) */
2497 #define SONY_PIC_FAN0_STATUS	0x93
sony_pic_set_fanspeed(unsigned long value)2498 static int sony_pic_set_fanspeed(unsigned long value)
2499 {
2500 	return ec_write(SONY_PIC_FAN0_STATUS, value);
2501 }
2502 
sony_pic_get_fanspeed(u8 * value)2503 static int sony_pic_get_fanspeed(u8 *value)
2504 {
2505 	return ec_read(SONY_PIC_FAN0_STATUS, value);
2506 }
2507 
sony_pic_fanspeed_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)2508 static ssize_t sony_pic_fanspeed_store(struct device *dev,
2509 		struct device_attribute *attr,
2510 		const char *buffer, size_t count)
2511 {
2512 	unsigned long value;
2513 	if (count > 31)
2514 		return -EINVAL;
2515 
2516 	value = simple_strtoul(buffer, NULL, 10);
2517 	if (sony_pic_set_fanspeed(value))
2518 		return -EIO;
2519 
2520 	return count;
2521 }
2522 
sony_pic_fanspeed_show(struct device * dev,struct device_attribute * attr,char * buffer)2523 static ssize_t sony_pic_fanspeed_show(struct device *dev,
2524 		struct device_attribute *attr, char *buffer)
2525 {
2526 	u8 value = 0;
2527 	if (sony_pic_get_fanspeed(&value))
2528 		return -EIO;
2529 
2530 	return snprintf(buffer, PAGE_SIZE, "%d\n", value);
2531 }
2532 
2533 #define SPIC_ATTR(_name, _mode)					\
2534 struct device_attribute spic_attr_##_name = __ATTR(_name,	\
2535 		_mode, sony_pic_## _name ##_show,		\
2536 		sony_pic_## _name ##_store)
2537 
2538 static SPIC_ATTR(bluetoothpower, 0644);
2539 static SPIC_ATTR(wwanpower, 0644);
2540 static SPIC_ATTR(fanspeed, 0644);
2541 
2542 static struct attribute *spic_attributes[] = {
2543 	&spic_attr_bluetoothpower.attr,
2544 	&spic_attr_wwanpower.attr,
2545 	&spic_attr_fanspeed.attr,
2546 	NULL
2547 };
2548 
2549 static struct attribute_group spic_attribute_group = {
2550 	.attrs = spic_attributes
2551 };
2552 
2553 /******** SONYPI compatibility **********/
2554 #ifdef CONFIG_SONYPI_COMPAT
2555 
2556 /* battery / brightness / temperature  addresses */
2557 #define SONYPI_BAT_FLAGS	0x81
2558 #define SONYPI_LCD_LIGHT	0x96
2559 #define SONYPI_BAT1_PCTRM	0xa0
2560 #define SONYPI_BAT1_LEFT	0xa2
2561 #define SONYPI_BAT1_MAXRT	0xa4
2562 #define SONYPI_BAT2_PCTRM	0xa8
2563 #define SONYPI_BAT2_LEFT	0xaa
2564 #define SONYPI_BAT2_MAXRT	0xac
2565 #define SONYPI_BAT1_MAXTK	0xb0
2566 #define SONYPI_BAT1_FULL	0xb2
2567 #define SONYPI_BAT2_MAXTK	0xb8
2568 #define SONYPI_BAT2_FULL	0xba
2569 #define SONYPI_TEMP_STATUS	0xC1
2570 
2571 struct sonypi_compat_s {
2572 	struct fasync_struct	*fifo_async;
2573 	struct kfifo		fifo;
2574 	spinlock_t		fifo_lock;
2575 	wait_queue_head_t	fifo_proc_list;
2576 	atomic_t		open_count;
2577 };
2578 static struct sonypi_compat_s sonypi_compat = {
2579 	.open_count = ATOMIC_INIT(0),
2580 };
2581 
sonypi_misc_fasync(int fd,struct file * filp,int on)2582 static int sonypi_misc_fasync(int fd, struct file *filp, int on)
2583 {
2584 	return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
2585 }
2586 
sonypi_misc_release(struct inode * inode,struct file * file)2587 static int sonypi_misc_release(struct inode *inode, struct file *file)
2588 {
2589 	atomic_dec(&sonypi_compat.open_count);
2590 	return 0;
2591 }
2592 
sonypi_misc_open(struct inode * inode,struct file * file)2593 static int sonypi_misc_open(struct inode *inode, struct file *file)
2594 {
2595 	/* Flush input queue on first open */
2596 	unsigned long flags;
2597 
2598 	spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
2599 
2600 	if (atomic_inc_return(&sonypi_compat.open_count) == 1)
2601 		kfifo_reset(&sonypi_compat.fifo);
2602 
2603 	spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
2604 
2605 	return 0;
2606 }
2607 
sonypi_misc_read(struct file * file,char __user * buf,size_t count,loff_t * pos)2608 static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
2609 				size_t count, loff_t *pos)
2610 {
2611 	ssize_t ret;
2612 	unsigned char c;
2613 
2614 	if ((kfifo_len(&sonypi_compat.fifo) == 0) &&
2615 	    (file->f_flags & O_NONBLOCK))
2616 		return -EAGAIN;
2617 
2618 	ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
2619 				       kfifo_len(&sonypi_compat.fifo) != 0);
2620 	if (ret)
2621 		return ret;
2622 
2623 	while (ret < count &&
2624 	       (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c),
2625 			  &sonypi_compat.fifo_lock) == sizeof(c))) {
2626 		if (put_user(c, buf++))
2627 			return -EFAULT;
2628 		ret++;
2629 	}
2630 
2631 	if (ret > 0) {
2632 		struct inode *inode = file->f_path.dentry->d_inode;
2633 		inode->i_atime = current_fs_time(inode->i_sb);
2634 	}
2635 
2636 	return ret;
2637 }
2638 
sonypi_misc_poll(struct file * file,poll_table * wait)2639 static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
2640 {
2641 	poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
2642 	if (kfifo_len(&sonypi_compat.fifo))
2643 		return POLLIN | POLLRDNORM;
2644 	return 0;
2645 }
2646 
ec_read16(u8 addr,u16 * value)2647 static int ec_read16(u8 addr, u16 *value)
2648 {
2649 	u8 val_lb, val_hb;
2650 	if (ec_read(addr, &val_lb))
2651 		return -1;
2652 	if (ec_read(addr + 1, &val_hb))
2653 		return -1;
2654 	*value = val_lb | (val_hb << 8);
2655 	return 0;
2656 }
2657 
sonypi_misc_ioctl(struct file * fp,unsigned int cmd,unsigned long arg)2658 static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
2659 							unsigned long arg)
2660 {
2661 	int ret = 0;
2662 	void __user *argp = (void __user *)arg;
2663 	u8 val8;
2664 	u16 val16;
2665 	int value;
2666 
2667 	mutex_lock(&spic_dev.lock);
2668 	switch (cmd) {
2669 	case SONYPI_IOCGBRT:
2670 		if (sony_bl_props.dev == NULL) {
2671 			ret = -EIO;
2672 			break;
2673 		}
2674 		if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) {
2675 			ret = -EIO;
2676 			break;
2677 		}
2678 		val8 = ((value & 0xff) - 1) << 5;
2679 		if (copy_to_user(argp, &val8, sizeof(val8)))
2680 				ret = -EFAULT;
2681 		break;
2682 	case SONYPI_IOCSBRT:
2683 		if (sony_bl_props.dev == NULL) {
2684 			ret = -EIO;
2685 			break;
2686 		}
2687 		if (copy_from_user(&val8, argp, sizeof(val8))) {
2688 			ret = -EFAULT;
2689 			break;
2690 		}
2691 		if (acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
2692 				(val8 >> 5) + 1, NULL)) {
2693 			ret = -EIO;
2694 			break;
2695 		}
2696 		/* sync the backlight device status */
2697 		sony_bl_props.dev->props.brightness =
2698 		    sony_backlight_get_brightness(sony_bl_props.dev);
2699 		break;
2700 	case SONYPI_IOCGBAT1CAP:
2701 		if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
2702 			ret = -EIO;
2703 			break;
2704 		}
2705 		if (copy_to_user(argp, &val16, sizeof(val16)))
2706 			ret = -EFAULT;
2707 		break;
2708 	case SONYPI_IOCGBAT1REM:
2709 		if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
2710 			ret = -EIO;
2711 			break;
2712 		}
2713 		if (copy_to_user(argp, &val16, sizeof(val16)))
2714 			ret = -EFAULT;
2715 		break;
2716 	case SONYPI_IOCGBAT2CAP:
2717 		if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
2718 			ret = -EIO;
2719 			break;
2720 		}
2721 		if (copy_to_user(argp, &val16, sizeof(val16)))
2722 			ret = -EFAULT;
2723 		break;
2724 	case SONYPI_IOCGBAT2REM:
2725 		if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
2726 			ret = -EIO;
2727 			break;
2728 		}
2729 		if (copy_to_user(argp, &val16, sizeof(val16)))
2730 			ret = -EFAULT;
2731 		break;
2732 	case SONYPI_IOCGBATFLAGS:
2733 		if (ec_read(SONYPI_BAT_FLAGS, &val8)) {
2734 			ret = -EIO;
2735 			break;
2736 		}
2737 		val8 &= 0x07;
2738 		if (copy_to_user(argp, &val8, sizeof(val8)))
2739 			ret = -EFAULT;
2740 		break;
2741 	case SONYPI_IOCGBLUE:
2742 		val8 = spic_dev.bluetooth_power;
2743 		if (copy_to_user(argp, &val8, sizeof(val8)))
2744 			ret = -EFAULT;
2745 		break;
2746 	case SONYPI_IOCSBLUE:
2747 		if (copy_from_user(&val8, argp, sizeof(val8))) {
2748 			ret = -EFAULT;
2749 			break;
2750 		}
2751 		__sony_pic_set_bluetoothpower(val8);
2752 		break;
2753 	/* FAN Controls */
2754 	case SONYPI_IOCGFAN:
2755 		if (sony_pic_get_fanspeed(&val8)) {
2756 			ret = -EIO;
2757 			break;
2758 		}
2759 		if (copy_to_user(argp, &val8, sizeof(val8)))
2760 			ret = -EFAULT;
2761 		break;
2762 	case SONYPI_IOCSFAN:
2763 		if (copy_from_user(&val8, argp, sizeof(val8))) {
2764 			ret = -EFAULT;
2765 			break;
2766 		}
2767 		if (sony_pic_set_fanspeed(val8))
2768 			ret = -EIO;
2769 		break;
2770 	/* GET Temperature (useful under APM) */
2771 	case SONYPI_IOCGTEMP:
2772 		if (ec_read(SONYPI_TEMP_STATUS, &val8)) {
2773 			ret = -EIO;
2774 			break;
2775 		}
2776 		if (copy_to_user(argp, &val8, sizeof(val8)))
2777 			ret = -EFAULT;
2778 		break;
2779 	default:
2780 		ret = -EINVAL;
2781 	}
2782 	mutex_unlock(&spic_dev.lock);
2783 	return ret;
2784 }
2785 
2786 static const struct file_operations sonypi_misc_fops = {
2787 	.owner		= THIS_MODULE,
2788 	.read		= sonypi_misc_read,
2789 	.poll		= sonypi_misc_poll,
2790 	.open		= sonypi_misc_open,
2791 	.release	= sonypi_misc_release,
2792 	.fasync		= sonypi_misc_fasync,
2793 	.unlocked_ioctl	= sonypi_misc_ioctl,
2794 	.llseek		= noop_llseek,
2795 };
2796 
2797 static struct miscdevice sonypi_misc_device = {
2798 	.minor		= MISC_DYNAMIC_MINOR,
2799 	.name		= "sonypi",
2800 	.fops		= &sonypi_misc_fops,
2801 };
2802 
sonypi_compat_report_event(u8 event)2803 static void sonypi_compat_report_event(u8 event)
2804 {
2805 	kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event,
2806 			sizeof(event), &sonypi_compat.fifo_lock);
2807 	kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
2808 	wake_up_interruptible(&sonypi_compat.fifo_proc_list);
2809 }
2810 
sonypi_compat_init(void)2811 static int sonypi_compat_init(void)
2812 {
2813 	int error;
2814 
2815 	spin_lock_init(&sonypi_compat.fifo_lock);
2816 	error =
2817 	 kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
2818 	if (error) {
2819 		pr_err("kfifo_alloc failed\n");
2820 		return error;
2821 	}
2822 
2823 	init_waitqueue_head(&sonypi_compat.fifo_proc_list);
2824 
2825 	if (minor != -1)
2826 		sonypi_misc_device.minor = minor;
2827 	error = misc_register(&sonypi_misc_device);
2828 	if (error) {
2829 		pr_err("misc_register failed\n");
2830 		goto err_free_kfifo;
2831 	}
2832 	if (minor == -1)
2833 		pr_info("device allocated minor is %d\n",
2834 			sonypi_misc_device.minor);
2835 
2836 	return 0;
2837 
2838 err_free_kfifo:
2839 	kfifo_free(&sonypi_compat.fifo);
2840 	return error;
2841 }
2842 
sonypi_compat_exit(void)2843 static void sonypi_compat_exit(void)
2844 {
2845 	misc_deregister(&sonypi_misc_device);
2846 	kfifo_free(&sonypi_compat.fifo);
2847 }
2848 #else
sonypi_compat_init(void)2849 static int sonypi_compat_init(void) { return 0; }
sonypi_compat_exit(void)2850 static void sonypi_compat_exit(void) { }
sonypi_compat_report_event(u8 event)2851 static void sonypi_compat_report_event(u8 event) { }
2852 #endif /* CONFIG_SONYPI_COMPAT */
2853 
2854 /*
2855  * ACPI callbacks
2856  */
2857 static acpi_status
sony_pic_read_possible_resource(struct acpi_resource * resource,void * context)2858 sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2859 {
2860 	u32 i;
2861 	struct sony_pic_dev *dev = (struct sony_pic_dev *)context;
2862 
2863 	switch (resource->type) {
2864 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
2865 		{
2866 			/* start IO enumeration */
2867 			struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
2868 			if (!ioport)
2869 				return AE_ERROR;
2870 
2871 			list_add(&ioport->list, &dev->ioports);
2872 			return AE_OK;
2873 		}
2874 
2875 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
2876 		/* end IO enumeration */
2877 		return AE_OK;
2878 
2879 	case ACPI_RESOURCE_TYPE_IRQ:
2880 		{
2881 			struct acpi_resource_irq *p = &resource->data.irq;
2882 			struct sony_pic_irq *interrupt = NULL;
2883 			if (!p || !p->interrupt_count) {
2884 				/*
2885 				 * IRQ descriptors may have no IRQ# bits set,
2886 				 * particularly those those w/ _STA disabled
2887 				 */
2888 				dprintk("Blank IRQ resource\n");
2889 				return AE_OK;
2890 			}
2891 			for (i = 0; i < p->interrupt_count; i++) {
2892 				if (!p->interrupts[i]) {
2893 					pr_warn("Invalid IRQ %d\n",
2894 						p->interrupts[i]);
2895 					continue;
2896 				}
2897 				interrupt = kzalloc(sizeof(*interrupt),
2898 						GFP_KERNEL);
2899 				if (!interrupt)
2900 					return AE_ERROR;
2901 
2902 				list_add(&interrupt->list, &dev->interrupts);
2903 				interrupt->irq.triggering = p->triggering;
2904 				interrupt->irq.polarity = p->polarity;
2905 				interrupt->irq.sharable = p->sharable;
2906 				interrupt->irq.interrupt_count = 1;
2907 				interrupt->irq.interrupts[0] = p->interrupts[i];
2908 			}
2909 			return AE_OK;
2910 		}
2911 	case ACPI_RESOURCE_TYPE_IO:
2912 		{
2913 			struct acpi_resource_io *io = &resource->data.io;
2914 			struct sony_pic_ioport *ioport =
2915 				list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
2916 			if (!io) {
2917 				dprintk("Blank IO resource\n");
2918 				return AE_OK;
2919 			}
2920 
2921 			if (!ioport->io1.minimum) {
2922 				memcpy(&ioport->io1, io, sizeof(*io));
2923 				dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
2924 						ioport->io1.address_length);
2925 			}
2926 			else if (!ioport->io2.minimum) {
2927 				memcpy(&ioport->io2, io, sizeof(*io));
2928 				dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
2929 						ioport->io2.address_length);
2930 			}
2931 			else {
2932 				pr_err("Unknown SPIC Type, more than 2 IO Ports\n");
2933 				return AE_ERROR;
2934 			}
2935 			return AE_OK;
2936 		}
2937 	default:
2938 		dprintk("Resource %d isn't an IRQ nor an IO port\n",
2939 			resource->type);
2940 
2941 	case ACPI_RESOURCE_TYPE_END_TAG:
2942 		return AE_OK;
2943 	}
2944 	return AE_CTRL_TERMINATE;
2945 }
2946 
sony_pic_possible_resources(struct acpi_device * device)2947 static int sony_pic_possible_resources(struct acpi_device *device)
2948 {
2949 	int result = 0;
2950 	acpi_status status = AE_OK;
2951 
2952 	if (!device)
2953 		return -EINVAL;
2954 
2955 	/* get device status */
2956 	/* see acpi_pci_link_get_current acpi_pci_link_get_possible */
2957 	dprintk("Evaluating _STA\n");
2958 	result = acpi_bus_get_status(device);
2959 	if (result) {
2960 		pr_warn("Unable to read status\n");
2961 		goto end;
2962 	}
2963 
2964 	if (!device->status.enabled)
2965 		dprintk("Device disabled\n");
2966 	else
2967 		dprintk("Device enabled\n");
2968 
2969 	/*
2970 	 * Query and parse 'method'
2971 	 */
2972 	dprintk("Evaluating %s\n", METHOD_NAME__PRS);
2973 	status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
2974 			sony_pic_read_possible_resource, &spic_dev);
2975 	if (ACPI_FAILURE(status)) {
2976 		pr_warn("Failure evaluating %s\n", METHOD_NAME__PRS);
2977 		result = -ENODEV;
2978 	}
2979 end:
2980 	return result;
2981 }
2982 
2983 /*
2984  *  Disable the spic device by calling its _DIS method
2985  */
sony_pic_disable(struct acpi_device * device)2986 static int sony_pic_disable(struct acpi_device *device)
2987 {
2988 	acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL,
2989 					       NULL);
2990 
2991 	if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND)
2992 		return -ENXIO;
2993 
2994 	dprintk("Device disabled\n");
2995 	return 0;
2996 }
2997 
2998 
2999 /*
3000  *  Based on drivers/acpi/pci_link.c:acpi_pci_link_set
3001  *
3002  *  Call _SRS to set current resources
3003  */
sony_pic_enable(struct acpi_device * device,struct sony_pic_ioport * ioport,struct sony_pic_irq * irq)3004 static int sony_pic_enable(struct acpi_device *device,
3005 		struct sony_pic_ioport *ioport, struct sony_pic_irq *irq)
3006 {
3007 	acpi_status status;
3008 	int result = 0;
3009 	/* Type 1 resource layout is:
3010 	 *    IO
3011 	 *    IO
3012 	 *    IRQNoFlags
3013 	 *    End
3014 	 *
3015 	 * Type 2 and 3 resource layout is:
3016 	 *    IO
3017 	 *    IRQNoFlags
3018 	 *    End
3019 	 */
3020 	struct {
3021 		struct acpi_resource res1;
3022 		struct acpi_resource res2;
3023 		struct acpi_resource res3;
3024 		struct acpi_resource res4;
3025 	} *resource;
3026 	struct acpi_buffer buffer = { 0, NULL };
3027 
3028 	if (!ioport || !irq)
3029 		return -EINVAL;
3030 
3031 	/* init acpi_buffer */
3032 	resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
3033 	if (!resource)
3034 		return -ENOMEM;
3035 
3036 	buffer.length = sizeof(*resource) + 1;
3037 	buffer.pointer = resource;
3038 
3039 	/* setup Type 1 resources */
3040 	if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
3041 
3042 		/* setup io resources */
3043 		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
3044 		resource->res1.length = sizeof(struct acpi_resource);
3045 		memcpy(&resource->res1.data.io, &ioport->io1,
3046 				sizeof(struct acpi_resource_io));
3047 
3048 		resource->res2.type = ACPI_RESOURCE_TYPE_IO;
3049 		resource->res2.length = sizeof(struct acpi_resource);
3050 		memcpy(&resource->res2.data.io, &ioport->io2,
3051 				sizeof(struct acpi_resource_io));
3052 
3053 		/* setup irq resource */
3054 		resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
3055 		resource->res3.length = sizeof(struct acpi_resource);
3056 		memcpy(&resource->res3.data.irq, &irq->irq,
3057 				sizeof(struct acpi_resource_irq));
3058 		/* we requested a shared irq */
3059 		resource->res3.data.irq.sharable = ACPI_SHARED;
3060 
3061 		resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
3062 
3063 	}
3064 	/* setup Type 2/3 resources */
3065 	else {
3066 		/* setup io resource */
3067 		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
3068 		resource->res1.length = sizeof(struct acpi_resource);
3069 		memcpy(&resource->res1.data.io, &ioport->io1,
3070 				sizeof(struct acpi_resource_io));
3071 
3072 		/* setup irq resource */
3073 		resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
3074 		resource->res2.length = sizeof(struct acpi_resource);
3075 		memcpy(&resource->res2.data.irq, &irq->irq,
3076 				sizeof(struct acpi_resource_irq));
3077 		/* we requested a shared irq */
3078 		resource->res2.data.irq.sharable = ACPI_SHARED;
3079 
3080 		resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
3081 	}
3082 
3083 	/* Attempt to set the resource */
3084 	dprintk("Evaluating _SRS\n");
3085 	status = acpi_set_current_resources(device->handle, &buffer);
3086 
3087 	/* check for total failure */
3088 	if (ACPI_FAILURE(status)) {
3089 		pr_err("Error evaluating _SRS\n");
3090 		result = -ENODEV;
3091 		goto end;
3092 	}
3093 
3094 	/* Necessary device initializations calls (from sonypi) */
3095 	sony_pic_call1(0x82);
3096 	sony_pic_call2(0x81, 0xff);
3097 	sony_pic_call1(compat ? 0x92 : 0x82);
3098 
3099 end:
3100 	kfree(resource);
3101 	return result;
3102 }
3103 
3104 /*****************
3105  *
3106  * ISR: some event is available
3107  *
3108  *****************/
sony_pic_irq(int irq,void * dev_id)3109 static irqreturn_t sony_pic_irq(int irq, void *dev_id)
3110 {
3111 	int i, j;
3112 	u8 ev = 0;
3113 	u8 data_mask = 0;
3114 	u8 device_event = 0;
3115 
3116 	struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
3117 
3118 	ev = inb_p(dev->cur_ioport->io1.minimum);
3119 	if (dev->cur_ioport->io2.minimum)
3120 		data_mask = inb_p(dev->cur_ioport->io2.minimum);
3121 	else
3122 		data_mask = inb_p(dev->cur_ioport->io1.minimum +
3123 				dev->evport_offset);
3124 
3125 	dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
3126 			ev, data_mask, dev->cur_ioport->io1.minimum,
3127 			dev->evport_offset);
3128 
3129 	if (ev == 0x00 || ev == 0xff)
3130 		return IRQ_HANDLED;
3131 
3132 	for (i = 0; dev->event_types[i].mask; i++) {
3133 
3134 		if ((data_mask & dev->event_types[i].data) !=
3135 		    dev->event_types[i].data)
3136 			continue;
3137 
3138 		if (!(mask & dev->event_types[i].mask))
3139 			continue;
3140 
3141 		for (j = 0; dev->event_types[i].events[j].event; j++) {
3142 			if (ev == dev->event_types[i].events[j].data) {
3143 				device_event =
3144 					dev->event_types[i].events[j].event;
3145 				/* some events may require ignoring */
3146 				if (!device_event)
3147 					return IRQ_HANDLED;
3148 				goto found;
3149 			}
3150 		}
3151 	}
3152 	/* Still not able to decode the event try to pass
3153 	 * it over to the minidriver
3154 	 */
3155 	if (dev->handle_irq && dev->handle_irq(data_mask, ev) == 0)
3156 		return IRQ_HANDLED;
3157 
3158 	dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
3159 			ev, data_mask, dev->cur_ioport->io1.minimum,
3160 			dev->evport_offset);
3161 	return IRQ_HANDLED;
3162 
3163 found:
3164 	sony_laptop_report_input_event(device_event);
3165 	acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
3166 	sonypi_compat_report_event(device_event);
3167 	return IRQ_HANDLED;
3168 }
3169 
3170 /*****************
3171  *
3172  *  ACPI driver
3173  *
3174  *****************/
sony_pic_remove(struct acpi_device * device,int type)3175 static int sony_pic_remove(struct acpi_device *device, int type)
3176 {
3177 	struct sony_pic_ioport *io, *tmp_io;
3178 	struct sony_pic_irq *irq, *tmp_irq;
3179 
3180 	if (sony_pic_disable(device)) {
3181 		pr_err("Couldn't disable device\n");
3182 		return -ENXIO;
3183 	}
3184 
3185 	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
3186 	release_region(spic_dev.cur_ioport->io1.minimum,
3187 			spic_dev.cur_ioport->io1.address_length);
3188 	if (spic_dev.cur_ioport->io2.minimum)
3189 		release_region(spic_dev.cur_ioport->io2.minimum,
3190 				spic_dev.cur_ioport->io2.address_length);
3191 
3192 	sonypi_compat_exit();
3193 
3194 	sony_laptop_remove_input();
3195 
3196 	/* pf attrs */
3197 	sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
3198 	sony_pf_remove();
3199 
3200 	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
3201 		list_del(&io->list);
3202 		kfree(io);
3203 	}
3204 	list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
3205 		list_del(&irq->list);
3206 		kfree(irq);
3207 	}
3208 	spic_dev.cur_ioport = NULL;
3209 	spic_dev.cur_irq = NULL;
3210 
3211 	dprintk(SONY_PIC_DRIVER_NAME " removed.\n");
3212 	return 0;
3213 }
3214 
sony_pic_add(struct acpi_device * device)3215 static int sony_pic_add(struct acpi_device *device)
3216 {
3217 	int result;
3218 	struct sony_pic_ioport *io, *tmp_io;
3219 	struct sony_pic_irq *irq, *tmp_irq;
3220 
3221 	pr_info("%s v%s\n", SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
3222 
3223 	spic_dev.acpi_dev = device;
3224 	strcpy(acpi_device_class(device), "sony/hotkey");
3225 	sony_pic_detect_device_type(&spic_dev);
3226 	mutex_init(&spic_dev.lock);
3227 
3228 	/* read _PRS resources */
3229 	result = sony_pic_possible_resources(device);
3230 	if (result) {
3231 		pr_err("Unable to read possible resources\n");
3232 		goto err_free_resources;
3233 	}
3234 
3235 	/* setup input devices and helper fifo */
3236 	result = sony_laptop_setup_input(device);
3237 	if (result) {
3238 		pr_err("Unable to create input devices\n");
3239 		goto err_free_resources;
3240 	}
3241 
3242 	if (sonypi_compat_init())
3243 		goto err_remove_input;
3244 
3245 	/* request io port */
3246 	list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
3247 		if (request_region(io->io1.minimum, io->io1.address_length,
3248 					"Sony Programmable I/O Device")) {
3249 			dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
3250 					io->io1.minimum, io->io1.maximum,
3251 					io->io1.address_length);
3252 			/* Type 1 have 2 ioports */
3253 			if (io->io2.minimum) {
3254 				if (request_region(io->io2.minimum,
3255 						io->io2.address_length,
3256 						"Sony Programmable I/O Device")) {
3257 					dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
3258 							io->io2.minimum, io->io2.maximum,
3259 							io->io2.address_length);
3260 					spic_dev.cur_ioport = io;
3261 					break;
3262 				}
3263 				else {
3264 					dprintk("Unable to get I/O port2: "
3265 							"0x%.4x (0x%.4x) + 0x%.2x\n",
3266 							io->io2.minimum, io->io2.maximum,
3267 							io->io2.address_length);
3268 					release_region(io->io1.minimum,
3269 							io->io1.address_length);
3270 				}
3271 			}
3272 			else {
3273 				spic_dev.cur_ioport = io;
3274 				break;
3275 			}
3276 		}
3277 	}
3278 	if (!spic_dev.cur_ioport) {
3279 		pr_err("Failed to request_region\n");
3280 		result = -ENODEV;
3281 		goto err_remove_compat;
3282 	}
3283 
3284 	/* request IRQ */
3285 	list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
3286 		if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
3287 					0, "sony-laptop", &spic_dev)) {
3288 			dprintk("IRQ: %d - triggering: %d - "
3289 					"polarity: %d - shr: %d\n",
3290 					irq->irq.interrupts[0],
3291 					irq->irq.triggering,
3292 					irq->irq.polarity,
3293 					irq->irq.sharable);
3294 			spic_dev.cur_irq = irq;
3295 			break;
3296 		}
3297 	}
3298 	if (!spic_dev.cur_irq) {
3299 		pr_err("Failed to request_irq\n");
3300 		result = -ENODEV;
3301 		goto err_release_region;
3302 	}
3303 
3304 	/* set resource status _SRS */
3305 	result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
3306 	if (result) {
3307 		pr_err("Couldn't enable device\n");
3308 		goto err_free_irq;
3309 	}
3310 
3311 	spic_dev.bluetooth_power = -1;
3312 	/* create device attributes */
3313 	result = sony_pf_add();
3314 	if (result)
3315 		goto err_disable_device;
3316 
3317 	result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
3318 	if (result)
3319 		goto err_remove_pf;
3320 
3321 	return 0;
3322 
3323 err_remove_pf:
3324 	sony_pf_remove();
3325 
3326 err_disable_device:
3327 	sony_pic_disable(device);
3328 
3329 err_free_irq:
3330 	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
3331 
3332 err_release_region:
3333 	release_region(spic_dev.cur_ioport->io1.minimum,
3334 			spic_dev.cur_ioport->io1.address_length);
3335 	if (spic_dev.cur_ioport->io2.minimum)
3336 		release_region(spic_dev.cur_ioport->io2.minimum,
3337 				spic_dev.cur_ioport->io2.address_length);
3338 
3339 err_remove_compat:
3340 	sonypi_compat_exit();
3341 
3342 err_remove_input:
3343 	sony_laptop_remove_input();
3344 
3345 err_free_resources:
3346 	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
3347 		list_del(&io->list);
3348 		kfree(io);
3349 	}
3350 	list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
3351 		list_del(&irq->list);
3352 		kfree(irq);
3353 	}
3354 	spic_dev.cur_ioport = NULL;
3355 	spic_dev.cur_irq = NULL;
3356 
3357 	return result;
3358 }
3359 
sony_pic_suspend(struct acpi_device * device,pm_message_t state)3360 static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
3361 {
3362 	if (sony_pic_disable(device))
3363 		return -ENXIO;
3364 	return 0;
3365 }
3366 
sony_pic_resume(struct acpi_device * device)3367 static int sony_pic_resume(struct acpi_device *device)
3368 {
3369 	sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
3370 	return 0;
3371 }
3372 
3373 static const struct acpi_device_id sony_pic_device_ids[] = {
3374 	{SONY_PIC_HID, 0},
3375 	{"", 0},
3376 };
3377 
3378 static struct acpi_driver sony_pic_driver = {
3379 	.name = SONY_PIC_DRIVER_NAME,
3380 	.class = SONY_PIC_CLASS,
3381 	.ids = sony_pic_device_ids,
3382 	.owner = THIS_MODULE,
3383 	.ops = {
3384 		.add = sony_pic_add,
3385 		.remove = sony_pic_remove,
3386 		.suspend = sony_pic_suspend,
3387 		.resume = sony_pic_resume,
3388 		},
3389 };
3390 
3391 static struct dmi_system_id __initdata sonypi_dmi_table[] = {
3392 	{
3393 		.ident = "Sony Vaio",
3394 		.matches = {
3395 			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
3396 			DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"),
3397 		},
3398 	},
3399 	{
3400 		.ident = "Sony Vaio",
3401 		.matches = {
3402 			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
3403 			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
3404 		},
3405 	},
3406 	{ }
3407 };
3408 
sony_laptop_init(void)3409 static int __init sony_laptop_init(void)
3410 {
3411 	int result;
3412 
3413 	if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
3414 		result = acpi_bus_register_driver(&sony_pic_driver);
3415 		if (result) {
3416 			pr_err("Unable to register SPIC driver\n");
3417 			goto out;
3418 		}
3419 		spic_drv_registered = 1;
3420 	}
3421 
3422 	result = acpi_bus_register_driver(&sony_nc_driver);
3423 	if (result) {
3424 		pr_err("Unable to register SNC driver\n");
3425 		goto out_unregister_pic;
3426 	}
3427 
3428 	return 0;
3429 
3430 out_unregister_pic:
3431 	if (spic_drv_registered)
3432 		acpi_bus_unregister_driver(&sony_pic_driver);
3433 out:
3434 	return result;
3435 }
3436 
sony_laptop_exit(void)3437 static void __exit sony_laptop_exit(void)
3438 {
3439 	acpi_bus_unregister_driver(&sony_nc_driver);
3440 	if (spic_drv_registered)
3441 		acpi_bus_unregister_driver(&sony_pic_driver);
3442 }
3443 
3444 module_init(sony_laptop_init);
3445 module_exit(sony_laptop_exit);
3446