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