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 = ∈
738 status = acpi_evaluate_object(handle, method, ¶ms, &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