1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <linux/kernel.h>
46#include <linux/module.h>
47#include <linux/moduleparam.h>
48#include <linux/init.h>
49#include <linux/types.h>
50#include <linux/backlight.h>
51#include <linux/platform_device.h>
52#include <linux/err.h>
53#include <linux/dmi.h>
54#include <linux/pci.h>
55#include <linux/interrupt.h>
56#include <linux/delay.h>
57#include <linux/input.h>
58#include <linux/kfifo.h>
59#include <linux/workqueue.h>
60#include <linux/acpi.h>
61#include <acpi/acpi_drivers.h>
62#include <acpi/acpi_bus.h>
63#include <asm/uaccess.h>
64#include <linux/sonypi.h>
65#include <linux/sony-laptop.h>
66#include <linux/rfkill.h>
67#ifdef CONFIG_SONYPI_COMPAT
68#include <linux/poll.h>
69#include <linux/miscdevice.h>
70#endif
71
72#define DRV_PFX "sony-laptop: "
73#define dprintk(msg...) do { \
74 if (debug) printk(KERN_WARNING DRV_PFX msg); \
75} while (0)
76
77#define SONY_LAPTOP_DRIVER_VERSION "0.6"
78
79#define SONY_NC_CLASS "sony-nc"
80#define SONY_NC_HID "SNY5001"
81#define SONY_NC_DRIVER_NAME "Sony Notebook Control Driver"
82
83#define SONY_PIC_CLASS "sony-pic"
84#define SONY_PIC_HID "SNY6001"
85#define SONY_PIC_DRIVER_NAME "Sony Programmable IO Control Driver"
86
87MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
88MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)");
89MODULE_LICENSE("GPL");
90MODULE_VERSION(SONY_LAPTOP_DRIVER_VERSION);
91
92static int debug;
93module_param(debug, int, 0);
94MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
95 "the development of this driver");
96
97static int no_spic;
98module_param(no_spic, int, 0444);
99MODULE_PARM_DESC(no_spic,
100 "set this if you don't want to enable the SPIC device");
101
102static int compat;
103module_param(compat, int, 0444);
104MODULE_PARM_DESC(compat,
105 "set this if you want to enable backward compatibility mode");
106
107static unsigned long mask = 0xffffffff;
108module_param(mask, ulong, 0644);
109MODULE_PARM_DESC(mask,
110 "set this to the mask of event you want to enable (see doc)");
111
112static int camera;
113module_param(camera, int, 0444);
114MODULE_PARM_DESC(camera,
115 "set this to 1 to enable Motion Eye camera controls "
116 "(only use it if you have a C1VE or C1VN model)");
117
118#ifdef CONFIG_SONYPI_COMPAT
119static int minor = -1;
120module_param(minor, int, 0);
121MODULE_PARM_DESC(minor,
122 "minor number of the misc device for the SPIC compatibility code, "
123 "default is -1 (automatic)");
124#endif
125
126enum sony_nc_rfkill {
127 SONY_WIFI,
128 SONY_BLUETOOTH,
129 SONY_WWAN,
130 SONY_WIMAX,
131 N_SONY_RFKILL,
132};
133
134static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
135static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
136static void sony_nc_rfkill_update(void);
137
138
139
140#define SONY_LAPTOP_BUF_SIZE 128
141struct sony_laptop_input_s {
142 atomic_t users;
143 struct input_dev *jog_dev;
144 struct input_dev *key_dev;
145 struct kfifo *fifo;
146 spinlock_t fifo_lock;
147 struct workqueue_struct *wq;
148};
149
150static struct sony_laptop_input_s sony_laptop_input = {
151 .users = ATOMIC_INIT(0),
152};
153
154struct sony_laptop_keypress {
155 struct input_dev *dev;
156 int key;
157};
158
159
160
161
162static int sony_laptop_input_index[] = {
163 -1,
164 -1,
165 -1,
166 -1,
167 -1,
168 -1,
169 -1,
170 0,
171 1,
172 2,
173 3,
174 4,
175 5,
176 6,
177 7,
178 8,
179 9,
180 10,
181 11,
182 12,
183 13,
184 14,
185 15,
186 16,
187 17,
188 18,
189 19,
190 20,
191 21,
192 22,
193 23,
194 24,
195 25,
196 26,
197 27,
198 28,
199 -1,
200 -1,
201 29,
202 30,
203 31,
204 32,
205 33,
206 34,
207 35,
208 36,
209 37,
210 38,
211 39,
212 40,
213 41,
214 42,
215 43,
216 44,
217 45,
218 46,
219 -1,
220 -1,
221 -1,
222 -1,
223 47,
224 48,
225 49,
226 50,
227 51,
228 52,
229 53,
230 54,
231 55,
232 56,
233 57,
234 -1,
235};
236
237static int sony_laptop_input_keycode_map[] = {
238 KEY_CAMERA,
239 KEY_RESERVED,
240 KEY_RESERVED,
241 KEY_RESERVED,
242 KEY_FN_ESC,
243 KEY_FN_F1,
244 KEY_FN_F2,
245 KEY_FN_F3,
246 KEY_FN_F4,
247 KEY_FN_F5,
248 KEY_FN_F6,
249 KEY_FN_F7,
250 KEY_FN_F8,
251 KEY_FN_F9,
252 KEY_FN_F10,
253 KEY_FN_F11,
254 KEY_FN_F12,
255 KEY_FN_F1,
256 KEY_FN_F2,
257 KEY_FN_D,
258 KEY_FN_E,
259 KEY_FN_F,
260 KEY_FN_S,
261 KEY_FN_B,
262 KEY_BLUETOOTH,
263 KEY_PROG1,
264 KEY_PROG2,
265 KEY_PROG3,
266 KEY_BACK,
267 KEY_BLUETOOTH,
268 KEY_BLUETOOTH,
269 KEY_HELP,
270 KEY_FN,
271 KEY_RESERVED,
272 KEY_RESERVED,
273 KEY_RESERVED,
274 KEY_RESERVED,
275 KEY_RESERVED,
276 KEY_RESERVED,
277 KEY_RESERVED,
278 KEY_RESERVED,
279 KEY_ZOOM,
280 BTN_THUMB,
281 KEY_RESERVED,
282 KEY_RESERVED,
283 KEY_RESERVED,
284 KEY_RESERVED,
285 KEY_WLAN,
286 KEY_WLAN,
287 KEY_ZOOMIN,
288 KEY_ZOOMOUT,
289 KEY_EJECTCD,
290 KEY_F13,
291 KEY_PROG4,
292 KEY_F14,
293 KEY_F15,
294 KEY_VOLUMEUP,
295 KEY_VOLUMEDOWN,
296};
297
298
299static void do_sony_laptop_release_key(struct work_struct *work)
300{
301 struct sony_laptop_keypress kp;
302
303 while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp,
304 sizeof(kp)) == sizeof(kp)) {
305 msleep(10);
306 input_report_key(kp.dev, kp.key, 0);
307 input_sync(kp.dev);
308 }
309}
310static DECLARE_WORK(sony_laptop_release_key_work,
311 do_sony_laptop_release_key);
312
313
314static void sony_laptop_report_input_event(u8 event)
315{
316 struct input_dev *jog_dev = sony_laptop_input.jog_dev;
317 struct input_dev *key_dev = sony_laptop_input.key_dev;
318 struct sony_laptop_keypress kp = { NULL };
319
320 if (event == SONYPI_EVENT_FNKEY_RELEASED ||
321 event == SONYPI_EVENT_ANYBUTTON_RELEASED) {
322
323 return;
324 }
325
326
327 switch (event) {
328
329 case SONYPI_EVENT_JOGDIAL_UP:
330 case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
331 input_report_rel(jog_dev, REL_WHEEL, 1);
332 input_sync(jog_dev);
333 return;
334
335 case SONYPI_EVENT_JOGDIAL_DOWN:
336 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
337 input_report_rel(jog_dev, REL_WHEEL, -1);
338 input_sync(jog_dev);
339 return;
340
341
342 case SONYPI_EVENT_JOGDIAL_PRESSED:
343 kp.key = BTN_MIDDLE;
344 kp.dev = jog_dev;
345 break;
346
347 default:
348 if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
349 dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
350 break;
351 }
352 if (sony_laptop_input_index[event] != -1) {
353 kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]];
354 if (kp.key != KEY_UNKNOWN)
355 kp.dev = key_dev;
356 }
357 break;
358 }
359
360 if (kp.dev) {
361 input_report_key(kp.dev, kp.key, 1);
362
363 input_event(kp.dev, EV_MSC, MSC_SCAN, event);
364 input_sync(kp.dev);
365 kfifo_put(sony_laptop_input.fifo,
366 (unsigned char *)&kp, sizeof(kp));
367
368 if (!work_pending(&sony_laptop_release_key_work))
369 queue_work(sony_laptop_input.wq,
370 &sony_laptop_release_key_work);
371 } else
372 dprintk("unknown input event %.2x\n", event);
373}
374
375static int sony_laptop_setup_input(struct acpi_device *acpi_device)
376{
377 struct input_dev *jog_dev;
378 struct input_dev *key_dev;
379 int i;
380 int error;
381
382
383 if (atomic_add_return(1, &sony_laptop_input.users) > 1)
384 return 0;
385
386
387 spin_lock_init(&sony_laptop_input.fifo_lock);
388 sony_laptop_input.fifo =
389 kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
390 &sony_laptop_input.fifo_lock);
391 if (IS_ERR(sony_laptop_input.fifo)) {
392 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
393 error = PTR_ERR(sony_laptop_input.fifo);
394 goto err_dec_users;
395 }
396
397
398 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop");
399 if (!sony_laptop_input.wq) {
400 printk(KERN_ERR DRV_PFX
401 "Unable to create workqueue.\n");
402 error = -ENXIO;
403 goto err_free_kfifo;
404 }
405
406
407 key_dev = input_allocate_device();
408 if (!key_dev) {
409 error = -ENOMEM;
410 goto err_destroy_wq;
411 }
412
413 key_dev->name = "Sony Vaio Keys";
414 key_dev->id.bustype = BUS_ISA;
415 key_dev->id.vendor = PCI_VENDOR_ID_SONY;
416 key_dev->dev.parent = &acpi_device->dev;
417
418
419 set_bit(EV_KEY, key_dev->evbit);
420 set_bit(EV_MSC, key_dev->evbit);
421 set_bit(MSC_SCAN, key_dev->mscbit);
422 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
423 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
424 key_dev->keycode = &sony_laptop_input_keycode_map;
425 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) {
426 if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) {
427 set_bit(sony_laptop_input_keycode_map[i],
428 key_dev->keybit);
429 }
430 }
431
432 error = input_register_device(key_dev);
433 if (error)
434 goto err_free_keydev;
435
436 sony_laptop_input.key_dev = key_dev;
437
438
439 jog_dev = input_allocate_device();
440 if (!jog_dev) {
441 error = -ENOMEM;
442 goto err_unregister_keydev;
443 }
444
445 jog_dev->name = "Sony Vaio Jogdial";
446 jog_dev->id.bustype = BUS_ISA;
447 jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
448 key_dev->dev.parent = &acpi_device->dev;
449
450 jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
451 jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE);
452 jog_dev->relbit[0] = BIT_MASK(REL_WHEEL);
453
454 error = input_register_device(jog_dev);
455 if (error)
456 goto err_free_jogdev;
457
458 sony_laptop_input.jog_dev = jog_dev;
459
460 return 0;
461
462err_free_jogdev:
463 input_free_device(jog_dev);
464
465err_unregister_keydev:
466 input_unregister_device(key_dev);
467
468 key_dev = NULL;
469
470err_free_keydev:
471 input_free_device(key_dev);
472
473err_destroy_wq:
474 destroy_workqueue(sony_laptop_input.wq);
475
476err_free_kfifo:
477 kfifo_free(sony_laptop_input.fifo);
478
479err_dec_users:
480 atomic_dec(&sony_laptop_input.users);
481 return error;
482}
483
484static void sony_laptop_remove_input(void)
485{
486
487 if (!atomic_dec_and_test(&sony_laptop_input.users))
488 return;
489
490
491 flush_workqueue(sony_laptop_input.wq);
492
493
494 input_unregister_device(sony_laptop_input.key_dev);
495 sony_laptop_input.key_dev = NULL;
496
497 if (sony_laptop_input.jog_dev) {
498 input_unregister_device(sony_laptop_input.jog_dev);
499 sony_laptop_input.jog_dev = NULL;
500 }
501
502 destroy_workqueue(sony_laptop_input.wq);
503 kfifo_free(sony_laptop_input.fifo);
504}
505
506
507
508static atomic_t sony_pf_users = ATOMIC_INIT(0);
509static struct platform_driver sony_pf_driver = {
510 .driver = {
511 .name = "sony-laptop",
512 .owner = THIS_MODULE,
513 }
514};
515static struct platform_device *sony_pf_device;
516
517static int sony_pf_add(void)
518{
519 int ret = 0;
520
521
522 if (atomic_add_return(1, &sony_pf_users) > 1)
523 return 0;
524
525 ret = platform_driver_register(&sony_pf_driver);
526 if (ret)
527 goto out;
528
529 sony_pf_device = platform_device_alloc("sony-laptop", -1);
530 if (!sony_pf_device) {
531 ret = -ENOMEM;
532 goto out_platform_registered;
533 }
534
535 ret = platform_device_add(sony_pf_device);
536 if (ret)
537 goto out_platform_alloced;
538
539 return 0;
540
541 out_platform_alloced:
542 platform_device_put(sony_pf_device);
543 sony_pf_device = NULL;
544 out_platform_registered:
545 platform_driver_unregister(&sony_pf_driver);
546 out:
547 atomic_dec(&sony_pf_users);
548 return ret;
549}
550
551static void sony_pf_remove(void)
552{
553
554 if (!atomic_dec_and_test(&sony_pf_users))
555 return;
556
557 platform_device_del(sony_pf_device);
558 platform_device_put(sony_pf_device);
559 platform_driver_unregister(&sony_pf_driver);
560}
561
562
563
564
565
566#define SONY_MAX_BRIGHTNESS 8
567
568#define SNC_VALIDATE_IN 0
569#define SNC_VALIDATE_OUT 1
570
571static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
572 char *);
573static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
574 const char *, size_t);
575static int boolean_validate(const int, const int);
576static int brightness_default_validate(const int, const int);
577
578struct sony_nc_value {
579 char *name;
580 char **acpiget;
581 char **acpiset;
582 int (*validate)(const int, const int);
583 int value;
584 int valid;
585 int debug;
586 struct device_attribute devattr;
587};
588
589#define SNC_HANDLE_NAMES(_name, _values...) \
590 static char *snc_##_name[] = { _values, NULL }
591
592#define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \
593 { \
594 .name = __stringify(_name), \
595 .acpiget = _getters, \
596 .acpiset = _setters, \
597 .validate = _validate, \
598 .debug = _debug, \
599 .devattr = __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \
600 }
601
602#define SNC_HANDLE_NULL { .name = NULL }
603
604SNC_HANDLE_NAMES(fnkey_get, "GHKE");
605
606SNC_HANDLE_NAMES(brightness_def_get, "GPBR");
607SNC_HANDLE_NAMES(brightness_def_set, "SPBR");
608
609SNC_HANDLE_NAMES(cdpower_get, "GCDP");
610SNC_HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
611
612SNC_HANDLE_NAMES(audiopower_get, "GAZP");
613SNC_HANDLE_NAMES(audiopower_set, "AZPW");
614
615SNC_HANDLE_NAMES(lanpower_get, "GLNP");
616SNC_HANDLE_NAMES(lanpower_set, "LNPW");
617
618SNC_HANDLE_NAMES(lidstate_get, "GLID");
619
620SNC_HANDLE_NAMES(indicatorlamp_get, "GILS");
621SNC_HANDLE_NAMES(indicatorlamp_set, "SILS");
622
623SNC_HANDLE_NAMES(gainbass_get, "GMGB");
624SNC_HANDLE_NAMES(gainbass_set, "CMGB");
625
626SNC_HANDLE_NAMES(PID_get, "GPID");
627
628SNC_HANDLE_NAMES(CTR_get, "GCTR");
629SNC_HANDLE_NAMES(CTR_set, "SCTR");
630
631SNC_HANDLE_NAMES(PCR_get, "GPCR");
632SNC_HANDLE_NAMES(PCR_set, "SPCR");
633
634SNC_HANDLE_NAMES(CMI_get, "GCMI");
635SNC_HANDLE_NAMES(CMI_set, "SCMI");
636
637static struct sony_nc_value sony_nc_values[] = {
638 SNC_HANDLE(brightness_default, snc_brightness_def_get,
639 snc_brightness_def_set, brightness_default_validate, 0),
640 SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
641 SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
642 SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
643 boolean_validate, 0),
644 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
645 boolean_validate, 1),
646 SNC_HANDLE(lidstate, snc_lidstate_get, NULL,
647 boolean_validate, 0),
648 SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set,
649 boolean_validate, 0),
650 SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set,
651 boolean_validate, 0),
652
653 SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1),
654 SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
655 SNC_HANDLE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
656 SNC_HANDLE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
657 SNC_HANDLE_NULL
658};
659
660static acpi_handle sony_nc_acpi_handle;
661static struct acpi_device *sony_nc_acpi_device = NULL;
662
663
664
665
666static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
667{
668 struct acpi_buffer output;
669 union acpi_object out_obj;
670 acpi_status status;
671
672 output.length = sizeof(out_obj);
673 output.pointer = &out_obj;
674
675 status = acpi_evaluate_object(handle, name, NULL, &output);
676 if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) {
677 *result = out_obj.integer.value;
678 return 0;
679 }
680
681 printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n");
682
683 return -1;
684}
685
686static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
687 int *result)
688{
689 struct acpi_object_list params;
690 union acpi_object in_obj;
691 struct acpi_buffer output;
692 union acpi_object out_obj;
693 acpi_status status;
694
695 params.count = 1;
696 params.pointer = &in_obj;
697 in_obj.type = ACPI_TYPE_INTEGER;
698 in_obj.integer.value = value;
699
700 output.length = sizeof(out_obj);
701 output.pointer = &out_obj;
702
703 status = acpi_evaluate_object(handle, name, ¶ms, &output);
704 if (status == AE_OK) {
705 if (result != NULL) {
706 if (out_obj.type != ACPI_TYPE_INTEGER) {
707 printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad "
708 "return type\n");
709 return -1;
710 }
711 *result = out_obj.integer.value;
712 }
713 return 0;
714 }
715
716 printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n");
717
718 return -1;
719}
720
721static int sony_find_snc_handle(int handle)
722{
723 int i;
724 int result;
725
726 for (i = 0x20; i < 0x30; i++) {
727 acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result);
728 if (result == handle)
729 return i-0x20;
730 }
731
732 return -1;
733}
734
735static int sony_call_snc_handle(int handle, int argument, int *result)
736{
737 int offset = sony_find_snc_handle(handle);
738
739 if (offset < 0)
740 return -1;
741
742 return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
743 result);
744}
745
746
747
748
749
750
751
752
753
754
755static int brightness_default_validate(const int direction, const int value)
756{
757 switch (direction) {
758 case SNC_VALIDATE_OUT:
759 return value - 1;
760 case SNC_VALIDATE_IN:
761 if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
762 return value + 1;
763 }
764 return -EINVAL;
765}
766
767
768
769
770
771
772static int boolean_validate(const int direction, const int value)
773{
774 if (direction == SNC_VALIDATE_IN) {
775 if (value != 0 && value != 1)
776 return -EINVAL;
777 }
778 return value;
779}
780
781
782
783
784static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
785 char *buffer)
786{
787 int value;
788 struct sony_nc_value *item =
789 container_of(attr, struct sony_nc_value, devattr);
790
791 if (!*item->acpiget)
792 return -EIO;
793
794 if (acpi_callgetfunc(sony_nc_acpi_handle, *item->acpiget, &value) < 0)
795 return -EIO;
796
797 if (item->validate)
798 value = item->validate(SNC_VALIDATE_OUT, value);
799
800 return snprintf(buffer, PAGE_SIZE, "%d\n", value);
801}
802
803static ssize_t sony_nc_sysfs_store(struct device *dev,
804 struct device_attribute *attr,
805 const char *buffer, size_t count)
806{
807 int value;
808 struct sony_nc_value *item =
809 container_of(attr, struct sony_nc_value, devattr);
810
811 if (!item->acpiset)
812 return -EIO;
813
814 if (count > 31)
815 return -EINVAL;
816
817 value = simple_strtoul(buffer, NULL, 10);
818
819 if (item->validate)
820 value = item->validate(SNC_VALIDATE_IN, value);
821
822 if (value < 0)
823 return value;
824
825 if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0)
826 return -EIO;
827 item->value = value;
828 item->valid = 1;
829 return count;
830}
831
832
833
834
835
836static int sony_backlight_update_status(struct backlight_device *bd)
837{
838 return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
839 bd->props.brightness + 1, NULL);
840}
841
842static int sony_backlight_get_brightness(struct backlight_device *bd)
843{
844 int value;
845
846 if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value))
847 return 0;
848
849 return value - 1;
850}
851
852static struct backlight_device *sony_backlight_device;
853static struct backlight_ops sony_backlight_ops = {
854 .update_status = sony_backlight_update_status,
855 .get_brightness = sony_backlight_get_brightness,
856};
857
858
859
860
861struct sony_nc_event {
862 u8 data;
863 u8 event;
864};
865
866static struct sony_nc_event sony_100_events[] = {
867 { 0x90, SONYPI_EVENT_PKEY_P1 },
868 { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
869 { 0x91, SONYPI_EVENT_PKEY_P2 },
870 { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
871 { 0x81, SONYPI_EVENT_FNKEY_F1 },
872 { 0x01, SONYPI_EVENT_FNKEY_RELEASED },
873 { 0x82, SONYPI_EVENT_FNKEY_F2 },
874 { 0x02, SONYPI_EVENT_FNKEY_RELEASED },
875 { 0x83, SONYPI_EVENT_FNKEY_F3 },
876 { 0x03, SONYPI_EVENT_FNKEY_RELEASED },
877 { 0x84, SONYPI_EVENT_FNKEY_F4 },
878 { 0x04, SONYPI_EVENT_FNKEY_RELEASED },
879 { 0x85, SONYPI_EVENT_FNKEY_F5 },
880 { 0x05, SONYPI_EVENT_FNKEY_RELEASED },
881 { 0x86, SONYPI_EVENT_FNKEY_F6 },
882 { 0x06, SONYPI_EVENT_FNKEY_RELEASED },
883 { 0x87, SONYPI_EVENT_FNKEY_F7 },
884 { 0x07, SONYPI_EVENT_FNKEY_RELEASED },
885 { 0x89, SONYPI_EVENT_FNKEY_F9 },
886 { 0x09, SONYPI_EVENT_FNKEY_RELEASED },
887 { 0x8A, SONYPI_EVENT_FNKEY_F10 },
888 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
889 { 0x8C, SONYPI_EVENT_FNKEY_F12 },
890 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
891 { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
892 { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
893 { 0, 0 },
894};
895
896static struct sony_nc_event sony_127_events[] = {
897 { 0x81, SONYPI_EVENT_MODEKEY_PRESSED },
898 { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED },
899 { 0x82, SONYPI_EVENT_PKEY_P1 },
900 { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED },
901 { 0x83, SONYPI_EVENT_PKEY_P2 },
902 { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED },
903 { 0x84, SONYPI_EVENT_PKEY_P3 },
904 { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED },
905 { 0x85, SONYPI_EVENT_PKEY_P4 },
906 { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
907 { 0x86, SONYPI_EVENT_PKEY_P5 },
908 { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
909 { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
910 { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
911 { 0, 0 },
912};
913
914
915
916
917static void sony_nc_notify(struct acpi_device *device, u32 event)
918{
919 u32 ev = event;
920
921 if (ev >= 0x90) {
922
923 int result;
924 int key_handle = 0;
925 ev -= 0x90;
926
927 if (sony_find_snc_handle(0x100) == ev)
928 key_handle = 0x100;
929 if (sony_find_snc_handle(0x127) == ev)
930 key_handle = 0x127;
931
932 if (key_handle) {
933 struct sony_nc_event *key_event;
934
935 if (sony_call_snc_handle(key_handle, 0x200, &result)) {
936 dprintk("sony_nc_notify, unable to decode"
937 " event 0x%.2x 0x%.2x\n", key_handle,
938 ev);
939
940 ev = event;
941 } else {
942 ev = result & 0xFF;
943
944 if (key_handle == 0x100)
945 key_event = sony_100_events;
946 else
947 key_event = sony_127_events;
948
949 for (; key_event->data; key_event++) {
950 if (key_event->data == ev) {
951 ev = key_event->event;
952 break;
953 }
954 }
955
956 if (!key_event->data)
957 printk(KERN_INFO DRV_PFX
958 "Unknown event: 0x%x 0x%x\n",
959 key_handle,
960 ev);
961 else
962 sony_laptop_report_input_event(ev);
963 }
964 } else if (sony_find_snc_handle(0x124) == ev) {
965 sony_nc_rfkill_update();
966 return;
967 }
968 } else
969 sony_laptop_report_input_event(ev);
970
971 dprintk("sony_nc_notify, event: 0x%.2x\n", ev);
972 acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
973}
974
975static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
976 void *context, void **return_value)
977{
978 struct acpi_device_info *info;
979
980 if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
981 printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n",
982 (char *)&info->name, info->param_count);
983
984 kfree(info);
985 }
986
987 return AE_OK;
988}
989
990
991
992
993static int sony_nc_function_setup(struct acpi_device *device)
994{
995 int result;
996
997
998 acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
999
1000
1001 sony_call_snc_handle(0x0100, 0, &result);
1002 sony_call_snc_handle(0x0101, 0, &result);
1003 sony_call_snc_handle(0x0102, 0x100, &result);
1004 sony_call_snc_handle(0x0127, 0, &result);
1005
1006 return 0;
1007}
1008
1009static int sony_nc_resume(struct acpi_device *device)
1010{
1011 struct sony_nc_value *item;
1012 acpi_handle handle;
1013
1014 for (item = sony_nc_values; item->name; item++) {
1015 int ret;
1016
1017 if (!item->valid)
1018 continue;
1019 ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
1020 item->value, NULL);
1021 if (ret < 0) {
1022 printk("%s: %d\n", __func__, ret);
1023 break;
1024 }
1025 }
1026
1027 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
1028 &handle))) {
1029 if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
1030 dprintk("ECON Method failed\n");
1031 }
1032
1033 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1034 &handle))) {
1035 dprintk("Doing SNC setup\n");
1036 sony_nc_function_setup(device);
1037 }
1038
1039
1040 if (sony_backlight_device &&
1041 sony_backlight_update_status(sony_backlight_device) < 0)
1042 printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
1043
1044
1045 sony_nc_rfkill_update();
1046
1047 return 0;
1048}
1049
1050static void sony_nc_rfkill_cleanup(void)
1051{
1052 int i;
1053
1054 for (i = 0; i < N_SONY_RFKILL; i++) {
1055 if (sony_rfkill_devices[i]) {
1056 rfkill_unregister(sony_rfkill_devices[i]);
1057 rfkill_destroy(sony_rfkill_devices[i]);
1058 }
1059 }
1060}
1061
1062static int sony_nc_rfkill_set(void *data, bool blocked)
1063{
1064 int result;
1065 int argument = sony_rfkill_address[(long) data] + 0x100;
1066
1067 if (!blocked)
1068 argument |= 0xff0000;
1069
1070 return sony_call_snc_handle(0x124, argument, &result);
1071}
1072
1073static const struct rfkill_ops sony_rfkill_ops = {
1074 .set_block = sony_nc_rfkill_set,
1075};
1076
1077static int sony_nc_setup_rfkill(struct acpi_device *device,
1078 enum sony_nc_rfkill nc_type)
1079{
1080 int err = 0;
1081 struct rfkill *rfk;
1082 enum rfkill_type type;
1083 const char *name;
1084 int result;
1085 bool hwblock;
1086
1087 switch (nc_type) {
1088 case SONY_WIFI:
1089 type = RFKILL_TYPE_WLAN;
1090 name = "sony-wifi";
1091 break;
1092 case SONY_BLUETOOTH:
1093 type = RFKILL_TYPE_BLUETOOTH;
1094 name = "sony-bluetooth";
1095 break;
1096 case SONY_WWAN:
1097 type = RFKILL_TYPE_WWAN;
1098 name = "sony-wwan";
1099 break;
1100 case SONY_WIMAX:
1101 type = RFKILL_TYPE_WIMAX;
1102 name = "sony-wimax";
1103 break;
1104 default:
1105 return -EINVAL;
1106 }
1107
1108 rfk = rfkill_alloc(name, &device->dev, type,
1109 &sony_rfkill_ops, (void *)nc_type);
1110 if (!rfk)
1111 return -ENOMEM;
1112
1113 sony_call_snc_handle(0x124, 0x200, &result);
1114 hwblock = !(result & 0x1);
1115 rfkill_set_hw_state(rfk, hwblock);
1116
1117 err = rfkill_register(rfk);
1118 if (err) {
1119 rfkill_destroy(rfk);
1120 return err;
1121 }
1122 sony_rfkill_devices[nc_type] = rfk;
1123 return err;
1124}
1125
1126static void sony_nc_rfkill_update()
1127{
1128 enum sony_nc_rfkill i;
1129 int result;
1130 bool hwblock;
1131
1132 sony_call_snc_handle(0x124, 0x200, &result);
1133 hwblock = !(result & 0x1);
1134
1135 for (i = 0; i < N_SONY_RFKILL; i++) {
1136 int argument = sony_rfkill_address[i];
1137
1138 if (!sony_rfkill_devices[i])
1139 continue;
1140
1141 if (hwblock) {
1142 if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
1143
1144 }
1145 continue;
1146 }
1147
1148 sony_call_snc_handle(0x124, argument, &result);
1149 rfkill_set_states(sony_rfkill_devices[i],
1150 !(result & 0xf), false);
1151 }
1152}
1153
1154static int sony_nc_rfkill_setup(struct acpi_device *device)
1155{
1156 int result, ret;
1157
1158 if (sony_find_snc_handle(0x124) == -1)
1159 return -1;
1160
1161 ret = sony_call_snc_handle(0x124, 0xb00, &result);
1162 if (ret) {
1163 printk(KERN_INFO DRV_PFX
1164 "Unable to enumerate rfkill devices: %x\n", ret);
1165 return ret;
1166 }
1167
1168 if (result & 0x1)
1169 sony_nc_setup_rfkill(device, SONY_WIFI);
1170 if (result & 0x2)
1171 sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1172 if (result & 0x1c)
1173 sony_nc_setup_rfkill(device, SONY_WWAN);
1174 if (result & 0x20)
1175 sony_nc_setup_rfkill(device, SONY_WIMAX);
1176
1177 return 0;
1178}
1179
1180static int sony_nc_add(struct acpi_device *device)
1181{
1182 acpi_status status;
1183 int result = 0;
1184 acpi_handle handle;
1185 struct sony_nc_value *item;
1186
1187 printk(KERN_INFO DRV_PFX "%s v%s.\n",
1188 SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
1189
1190 sony_nc_acpi_device = device;
1191 strcpy(acpi_device_class(device), "sony/hotkey");
1192
1193 sony_nc_acpi_handle = device->handle;
1194
1195
1196 result = acpi_bus_get_status(device);
1197
1198 if (!result && !device->status.present) {
1199 dprintk("Device not present\n");
1200 result = -ENODEV;
1201 goto outwalk;
1202 }
1203
1204 if (debug) {
1205 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
1206 1, sony_walk_callback, NULL, NULL);
1207 if (ACPI_FAILURE(status)) {
1208 printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
1209 result = -ENODEV;
1210 goto outwalk;
1211 }
1212 }
1213
1214 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
1215 &handle))) {
1216 if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
1217 dprintk("ECON Method failed\n");
1218 }
1219
1220 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1221 &handle))) {
1222 dprintk("Doing SNC setup\n");
1223 sony_nc_function_setup(device);
1224 sony_nc_rfkill_setup(device);
1225 }
1226
1227
1228 result = sony_laptop_setup_input(device);
1229 if (result) {
1230 printk(KERN_ERR DRV_PFX
1231 "Unable to create input devices.\n");
1232 goto outwalk;
1233 }
1234
1235 if (acpi_video_backlight_support()) {
1236 printk(KERN_INFO DRV_PFX "brightness ignored, must be "
1237 "controlled by ACPI video driver\n");
1238 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
1239 &handle))) {
1240 sony_backlight_device = backlight_device_register("sony", NULL,
1241 NULL,
1242 &sony_backlight_ops);
1243
1244 if (IS_ERR(sony_backlight_device)) {
1245 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
1246 sony_backlight_device = NULL;
1247 } else {
1248 sony_backlight_device->props.brightness =
1249 sony_backlight_get_brightness
1250 (sony_backlight_device);
1251 sony_backlight_device->props.max_brightness =
1252 SONY_MAX_BRIGHTNESS - 1;
1253 }
1254
1255 }
1256
1257 result = sony_pf_add();
1258 if (result)
1259 goto outbacklight;
1260
1261
1262 for (item = sony_nc_values; item->name; ++item) {
1263
1264 if (!debug && item->debug)
1265 continue;
1266
1267
1268 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
1269 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
1270 *item->acpiget,
1271 &handle))) {
1272 dprintk("Found %s getter: %s\n",
1273 item->name, *item->acpiget);
1274 item->devattr.attr.mode |= S_IRUGO;
1275 break;
1276 }
1277 }
1278
1279
1280 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
1281 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
1282 *item->acpiset,
1283 &handle))) {
1284 dprintk("Found %s setter: %s\n",
1285 item->name, *item->acpiset);
1286 item->devattr.attr.mode |= S_IWUSR;
1287 break;
1288 }
1289 }
1290
1291 if (item->devattr.attr.mode != 0) {
1292 result =
1293 device_create_file(&sony_pf_device->dev,
1294 &item->devattr);
1295 if (result)
1296 goto out_sysfs;
1297 }
1298 }
1299
1300 return 0;
1301
1302 out_sysfs:
1303 for (item = sony_nc_values; item->name; ++item) {
1304 device_remove_file(&sony_pf_device->dev, &item->devattr);
1305 }
1306 sony_pf_remove();
1307
1308 outbacklight:
1309 if (sony_backlight_device)
1310 backlight_device_unregister(sony_backlight_device);
1311
1312 sony_laptop_remove_input();
1313
1314 outwalk:
1315 sony_nc_rfkill_cleanup();
1316 return result;
1317}
1318
1319static int sony_nc_remove(struct acpi_device *device, int type)
1320{
1321 struct sony_nc_value *item;
1322
1323 if (sony_backlight_device)
1324 backlight_device_unregister(sony_backlight_device);
1325
1326 sony_nc_acpi_device = NULL;
1327
1328 for (item = sony_nc_values; item->name; ++item) {
1329 device_remove_file(&sony_pf_device->dev, &item->devattr);
1330 }
1331
1332 sony_pf_remove();
1333 sony_laptop_remove_input();
1334 sony_nc_rfkill_cleanup();
1335 dprintk(SONY_NC_DRIVER_NAME " removed.\n");
1336
1337 return 0;
1338}
1339
1340static const struct acpi_device_id sony_device_ids[] = {
1341 {SONY_NC_HID, 0},
1342 {SONY_PIC_HID, 0},
1343 {"", 0},
1344};
1345MODULE_DEVICE_TABLE(acpi, sony_device_ids);
1346
1347static const struct acpi_device_id sony_nc_device_ids[] = {
1348 {SONY_NC_HID, 0},
1349 {"", 0},
1350};
1351
1352static struct acpi_driver sony_nc_driver = {
1353 .name = SONY_NC_DRIVER_NAME,
1354 .class = SONY_NC_CLASS,
1355 .ids = sony_nc_device_ids,
1356 .owner = THIS_MODULE,
1357 .ops = {
1358 .add = sony_nc_add,
1359 .remove = sony_nc_remove,
1360 .resume = sony_nc_resume,
1361 .notify = sony_nc_notify,
1362 },
1363};
1364
1365
1366
1367#define SONYPI_DEVICE_TYPE1 0x00000001
1368#define SONYPI_DEVICE_TYPE2 0x00000002
1369#define SONYPI_DEVICE_TYPE3 0x00000004
1370#define SONYPI_DEVICE_TYPE4 0x00000008
1371
1372#define SONYPI_TYPE1_OFFSET 0x04
1373#define SONYPI_TYPE2_OFFSET 0x12
1374#define SONYPI_TYPE3_OFFSET 0x12
1375
1376struct sony_pic_ioport {
1377 struct acpi_resource_io io1;
1378 struct acpi_resource_io io2;
1379 struct list_head list;
1380};
1381
1382struct sony_pic_irq {
1383 struct acpi_resource_irq irq;
1384 struct list_head list;
1385};
1386
1387struct sonypi_eventtypes {
1388 u8 data;
1389 unsigned long mask;
1390 struct sonypi_event *events;
1391};
1392
1393struct sony_pic_dev {
1394 struct acpi_device *acpi_dev;
1395 struct sony_pic_irq *cur_irq;
1396 struct sony_pic_ioport *cur_ioport;
1397 struct list_head interrupts;
1398 struct list_head ioports;
1399 struct mutex lock;
1400 struct sonypi_eventtypes *event_types;
1401 int (*handle_irq)(const u8, const u8);
1402 int model;
1403 u16 evport_offset;
1404 u8 camera_power;
1405 u8 bluetooth_power;
1406 u8 wwan_power;
1407};
1408
1409static struct sony_pic_dev spic_dev = {
1410 .interrupts = LIST_HEAD_INIT(spic_dev.interrupts),
1411 .ioports = LIST_HEAD_INIT(spic_dev.ioports),
1412};
1413
1414static int spic_drv_registered;
1415
1416
1417#define SONYPI_JOGGER_MASK 0x00000001
1418#define SONYPI_CAPTURE_MASK 0x00000002
1419#define SONYPI_FNKEY_MASK 0x00000004
1420#define SONYPI_BLUETOOTH_MASK 0x00000008
1421#define SONYPI_PKEY_MASK 0x00000010
1422#define SONYPI_BACK_MASK 0x00000020
1423#define SONYPI_HELP_MASK 0x00000040
1424#define SONYPI_LID_MASK 0x00000080
1425#define SONYPI_ZOOM_MASK 0x00000100
1426#define SONYPI_THUMBPHRASE_MASK 0x00000200
1427#define SONYPI_MEYE_MASK 0x00000400
1428#define SONYPI_MEMORYSTICK_MASK 0x00000800
1429#define SONYPI_BATTERY_MASK 0x00001000
1430#define SONYPI_WIRELESS_MASK 0x00002000
1431
1432struct sonypi_event {
1433 u8 data;
1434 u8 event;
1435};
1436
1437
1438static struct sonypi_event sonypi_releaseev[] = {
1439 { 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED },
1440 { 0, 0 }
1441};
1442
1443
1444static struct sonypi_event sonypi_joggerev[] = {
1445 { 0x1f, SONYPI_EVENT_JOGDIAL_UP },
1446 { 0x01, SONYPI_EVENT_JOGDIAL_DOWN },
1447 { 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED },
1448 { 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED },
1449 { 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP },
1450 { 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN },
1451 { 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED },
1452 { 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED },
1453 { 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP },
1454 { 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN },
1455 { 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED },
1456 { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED },
1457 { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED },
1458 { 0, 0 }
1459};
1460
1461
1462static struct sonypi_event sonypi_captureev[] = {
1463 { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
1464 { 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
1465 { 0x40, SONYPI_EVENT_CAPTURE_PRESSED },
1466 { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
1467 { 0, 0 }
1468};
1469
1470
1471static struct sonypi_event sonypi_fnkeyev[] = {
1472 { 0x10, SONYPI_EVENT_FNKEY_ESC },
1473 { 0x11, SONYPI_EVENT_FNKEY_F1 },
1474 { 0x12, SONYPI_EVENT_FNKEY_F2 },
1475 { 0x13, SONYPI_EVENT_FNKEY_F3 },
1476 { 0x14, SONYPI_EVENT_FNKEY_F4 },
1477 { 0x15, SONYPI_EVENT_FNKEY_F5 },
1478 { 0x16, SONYPI_EVENT_FNKEY_F6 },
1479 { 0x17, SONYPI_EVENT_FNKEY_F7 },
1480 { 0x18, SONYPI_EVENT_FNKEY_F8 },
1481 { 0x19, SONYPI_EVENT_FNKEY_F9 },
1482 { 0x1a, SONYPI_EVENT_FNKEY_F10 },
1483 { 0x1b, SONYPI_EVENT_FNKEY_F11 },
1484 { 0x1c, SONYPI_EVENT_FNKEY_F12 },
1485 { 0x1f, SONYPI_EVENT_FNKEY_RELEASED },
1486 { 0x21, SONYPI_EVENT_FNKEY_1 },
1487 { 0x22, SONYPI_EVENT_FNKEY_2 },
1488 { 0x31, SONYPI_EVENT_FNKEY_D },
1489 { 0x32, SONYPI_EVENT_FNKEY_E },
1490 { 0x33, SONYPI_EVENT_FNKEY_F },
1491 { 0x34, SONYPI_EVENT_FNKEY_S },
1492 { 0x35, SONYPI_EVENT_FNKEY_B },
1493 { 0x36, SONYPI_EVENT_FNKEY_ONLY },
1494 { 0, 0 }
1495};
1496
1497
1498static struct sonypi_event sonypi_pkeyev[] = {
1499 { 0x01, SONYPI_EVENT_PKEY_P1 },
1500 { 0x02, SONYPI_EVENT_PKEY_P2 },
1501 { 0x04, SONYPI_EVENT_PKEY_P3 },
1502 { 0x20, SONYPI_EVENT_PKEY_P1 },
1503 { 0, 0 }
1504};
1505
1506
1507static struct sonypi_event sonypi_blueev[] = {
1508 { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
1509 { 0x59, SONYPI_EVENT_BLUETOOTH_ON },
1510 { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
1511 { 0, 0 }
1512};
1513
1514
1515static struct sonypi_event sonypi_wlessev[] = {
1516 { 0x59, SONYPI_EVENT_WIRELESS_ON },
1517 { 0x5a, SONYPI_EVENT_WIRELESS_OFF },
1518 { 0, 0 }
1519};
1520
1521
1522static struct sonypi_event sonypi_backev[] = {
1523 { 0x20, SONYPI_EVENT_BACK_PRESSED },
1524 { 0, 0 }
1525};
1526
1527
1528static struct sonypi_event sonypi_helpev[] = {
1529 { 0x3b, SONYPI_EVENT_HELP_PRESSED },
1530 { 0, 0 }
1531};
1532
1533
1534
1535static struct sonypi_event sonypi_lidev[] = {
1536 { 0x51, SONYPI_EVENT_LID_CLOSED },
1537 { 0x50, SONYPI_EVENT_LID_OPENED },
1538 { 0, 0 }
1539};
1540
1541
1542static struct sonypi_event sonypi_zoomev[] = {
1543 { 0x39, SONYPI_EVENT_ZOOM_PRESSED },
1544 { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED },
1545 { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED },
1546 { 0x04, SONYPI_EVENT_ZOOM_PRESSED },
1547 { 0, 0 }
1548};
1549
1550
1551static struct sonypi_event sonypi_thumbphraseev[] = {
1552 { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED },
1553 { 0, 0 }
1554};
1555
1556
1557static struct sonypi_event sonypi_meyeev[] = {
1558 { 0x00, SONYPI_EVENT_MEYE_FACE },
1559 { 0x01, SONYPI_EVENT_MEYE_OPPOSITE },
1560 { 0, 0 }
1561};
1562
1563
1564static struct sonypi_event sonypi_memorystickev[] = {
1565 { 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT },
1566 { 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT },
1567 { 0, 0 }
1568};
1569
1570
1571static struct sonypi_event sonypi_batteryev[] = {
1572 { 0x20, SONYPI_EVENT_BATTERY_INSERT },
1573 { 0x30, SONYPI_EVENT_BATTERY_REMOVE },
1574 { 0, 0 }
1575};
1576
1577
1578static struct sonypi_event sonypi_volumeev[] = {
1579 { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED },
1580 { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED },
1581 { 0, 0 }
1582};
1583
1584
1585static struct sonypi_event sonypi_brightnessev[] = {
1586 { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED },
1587 { 0, 0 }
1588};
1589
1590static struct sonypi_eventtypes type1_events[] = {
1591 { 0, 0xffffffff, sonypi_releaseev },
1592 { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
1593 { 0x30, SONYPI_LID_MASK, sonypi_lidev },
1594 { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
1595 { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
1596 { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
1597 { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
1598 { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
1599 { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
1600 { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
1601 { 0 },
1602};
1603static struct sonypi_eventtypes type2_events[] = {
1604 { 0, 0xffffffff, sonypi_releaseev },
1605 { 0x38, SONYPI_LID_MASK, sonypi_lidev },
1606 { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
1607 { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
1608 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
1609 { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
1610 { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
1611 { 0x11, SONYPI_BACK_MASK, sonypi_backev },
1612 { 0x21, SONYPI_HELP_MASK, sonypi_helpev },
1613 { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
1614 { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
1615 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
1616 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
1617 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
1618 { 0 },
1619};
1620static struct sonypi_eventtypes type3_events[] = {
1621 { 0, 0xffffffff, sonypi_releaseev },
1622 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
1623 { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
1624 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
1625 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
1626 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
1627 { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev },
1628 { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev },
1629 { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev },
1630 { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev },
1631 { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev },
1632 { 0 },
1633};
1634
1635
1636#define ITERATIONS_LONG 10000
1637#define ITERATIONS_SHORT 10
1638#define wait_on_command(command, iterations) { \
1639 unsigned int n = iterations; \
1640 while (--n && (command)) \
1641 udelay(1); \
1642 if (!n) \
1643 dprintk("command failed at %s : %s (line %d)\n", \
1644 __FILE__, __func__, __LINE__); \
1645}
1646
1647static u8 sony_pic_call1(u8 dev)
1648{
1649 u8 v1, v2;
1650
1651 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1652 ITERATIONS_LONG);
1653 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1654 v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
1655 v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
1656 dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1);
1657 return v2;
1658}
1659
1660static u8 sony_pic_call2(u8 dev, u8 fn)
1661{
1662 u8 v1;
1663
1664 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1665 ITERATIONS_LONG);
1666 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1667 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1668 ITERATIONS_LONG);
1669 outb(fn, spic_dev.cur_ioport->io1.minimum);
1670 v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
1671 dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1);
1672 return v1;
1673}
1674
1675static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
1676{
1677 u8 v1;
1678
1679 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1680 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1681 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1682 outb(fn, spic_dev.cur_ioport->io1.minimum);
1683 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1684 outb(v, spic_dev.cur_ioport->io1.minimum);
1685 v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
1686 dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
1687 dev, fn, v, v1);
1688 return v1;
1689}
1690
1691
1692
1693
1694static int type3_handle_irq(const u8 data_mask, const u8 ev)
1695{
1696
1697
1698
1699
1700
1701
1702
1703 if (data_mask == 0x31) {
1704 if (ev == 0x5c || ev == 0x5f)
1705 sony_pic_call1(0xA0);
1706 else if (ev == 0x61)
1707 sony_pic_call1(0xB3);
1708 return 0;
1709 }
1710 return 1;
1711}
1712
1713static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
1714{
1715 struct pci_dev *pcidev;
1716
1717 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1718 PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
1719 if (pcidev) {
1720 dev->model = SONYPI_DEVICE_TYPE1;
1721 dev->evport_offset = SONYPI_TYPE1_OFFSET;
1722 dev->event_types = type1_events;
1723 goto out;
1724 }
1725
1726 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1727 PCI_DEVICE_ID_INTEL_ICH6_1, NULL);
1728 if (pcidev) {
1729 dev->model = SONYPI_DEVICE_TYPE2;
1730 dev->evport_offset = SONYPI_TYPE2_OFFSET;
1731 dev->event_types = type2_events;
1732 goto out;
1733 }
1734
1735 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1736 PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
1737 if (pcidev) {
1738 dev->model = SONYPI_DEVICE_TYPE3;
1739 dev->handle_irq = type3_handle_irq;
1740 dev->evport_offset = SONYPI_TYPE3_OFFSET;
1741 dev->event_types = type3_events;
1742 goto out;
1743 }
1744
1745 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1746 PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
1747 if (pcidev) {
1748 dev->model = SONYPI_DEVICE_TYPE3;
1749 dev->handle_irq = type3_handle_irq;
1750 dev->evport_offset = SONYPI_TYPE3_OFFSET;
1751 dev->event_types = type3_events;
1752 goto out;
1753 }
1754
1755 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1756 PCI_DEVICE_ID_INTEL_ICH9_1, NULL);
1757 if (pcidev) {
1758 dev->model = SONYPI_DEVICE_TYPE3;
1759 dev->handle_irq = type3_handle_irq;
1760 dev->evport_offset = SONYPI_TYPE3_OFFSET;
1761 dev->event_types = type3_events;
1762 goto out;
1763 }
1764
1765
1766 dev->model = SONYPI_DEVICE_TYPE2;
1767 dev->evport_offset = SONYPI_TYPE2_OFFSET;
1768 dev->event_types = type2_events;
1769
1770out:
1771 if (pcidev)
1772 pci_dev_put(pcidev);
1773
1774 printk(KERN_INFO DRV_PFX "detected Type%d model\n",
1775 dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
1776 dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
1777}
1778
1779
1780#define SONYPI_CAMERA_PICTURE 5
1781#define SONYPI_CAMERA_CONTROL 0x10
1782
1783#define SONYPI_CAMERA_BRIGHTNESS 0
1784#define SONYPI_CAMERA_CONTRAST 1
1785#define SONYPI_CAMERA_HUE 2
1786#define SONYPI_CAMERA_COLOR 3
1787#define SONYPI_CAMERA_SHARPNESS 4
1788
1789#define SONYPI_CAMERA_EXPOSURE_MASK 0xC
1790#define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3
1791#define SONYPI_CAMERA_PICTURE_MODE_MASK 0x30
1792#define SONYPI_CAMERA_MUTE_MASK 0x40
1793
1794
1795#define SONYPI_CAMERA_AGC 6
1796#define SONYPI_CAMERA_AGC_MASK 0x30
1797#define SONYPI_CAMERA_SHUTTER_MASK 0x7
1798
1799#define SONYPI_CAMERA_SHUTDOWN_REQUEST 7
1800#define SONYPI_CAMERA_CONTROL 0x10
1801
1802#define SONYPI_CAMERA_STATUS 7
1803#define SONYPI_CAMERA_STATUS_READY 0x2
1804#define SONYPI_CAMERA_STATUS_POSITION 0x4
1805
1806#define SONYPI_DIRECTION_BACKWARDS 0x4
1807
1808#define SONYPI_CAMERA_REVISION 8
1809#define SONYPI_CAMERA_ROMVERSION 9
1810
1811static int __sony_pic_camera_ready(void)
1812{
1813 u8 v;
1814
1815 v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
1816 return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
1817}
1818
1819static int __sony_pic_camera_off(void)
1820{
1821 if (!camera) {
1822 printk(KERN_WARNING DRV_PFX "camera control not enabled\n");
1823 return -ENODEV;
1824 }
1825
1826 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
1827 SONYPI_CAMERA_MUTE_MASK),
1828 ITERATIONS_SHORT);
1829
1830 if (spic_dev.camera_power) {
1831 sony_pic_call2(0x91, 0);
1832 spic_dev.camera_power = 0;
1833 }
1834 return 0;
1835}
1836
1837static int __sony_pic_camera_on(void)
1838{
1839 int i, j, x;
1840
1841 if (!camera) {
1842 printk(KERN_WARNING DRV_PFX "camera control not enabled\n");
1843 return -ENODEV;
1844 }
1845
1846 if (spic_dev.camera_power)
1847 return 0;
1848
1849 for (j = 5; j > 0; j--) {
1850
1851 for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
1852 msleep(10);
1853 sony_pic_call1(0x93);
1854
1855 for (i = 400; i > 0; i--) {
1856 if (__sony_pic_camera_ready())
1857 break;
1858 msleep(10);
1859 }
1860 if (i)
1861 break;
1862 }
1863
1864 if (j == 0) {
1865 printk(KERN_WARNING DRV_PFX "failed to power on camera\n");
1866 return -ENODEV;
1867 }
1868
1869 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL,
1870 0x5a),
1871 ITERATIONS_SHORT);
1872
1873 spic_dev.camera_power = 1;
1874 return 0;
1875}
1876
1877
1878int sony_pic_camera_command(int command, u8 value)
1879{
1880 if (!camera)
1881 return -EIO;
1882
1883 mutex_lock(&spic_dev.lock);
1884
1885 switch (command) {
1886 case SONY_PIC_COMMAND_SETCAMERA:
1887 if (value)
1888 __sony_pic_camera_on();
1889 else
1890 __sony_pic_camera_off();
1891 break;
1892 case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
1893 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value),
1894 ITERATIONS_SHORT);
1895 break;
1896 case SONY_PIC_COMMAND_SETCAMERACONTRAST:
1897 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
1898 ITERATIONS_SHORT);
1899 break;
1900 case SONY_PIC_COMMAND_SETCAMERAHUE:
1901 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
1902 ITERATIONS_SHORT);
1903 break;
1904 case SONY_PIC_COMMAND_SETCAMERACOLOR:
1905 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
1906 ITERATIONS_SHORT);
1907 break;
1908 case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
1909 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
1910 ITERATIONS_SHORT);
1911 break;
1912 case SONY_PIC_COMMAND_SETCAMERAPICTURE:
1913 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
1914 ITERATIONS_SHORT);
1915 break;
1916 case SONY_PIC_COMMAND_SETCAMERAAGC:
1917 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
1918 ITERATIONS_SHORT);
1919 break;
1920 default:
1921 printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n",
1922 command);
1923 break;
1924 }
1925 mutex_unlock(&spic_dev.lock);
1926 return 0;
1927}
1928EXPORT_SYMBOL(sony_pic_camera_command);
1929
1930
1931static void __sony_pic_set_wwanpower(u8 state)
1932{
1933 state = !!state;
1934 if (spic_dev.wwan_power == state)
1935 return;
1936 sony_pic_call2(0xB0, state);
1937 sony_pic_call1(0x82);
1938 spic_dev.wwan_power = state;
1939}
1940
1941static ssize_t sony_pic_wwanpower_store(struct device *dev,
1942 struct device_attribute *attr,
1943 const char *buffer, size_t count)
1944{
1945 unsigned long value;
1946 if (count > 31)
1947 return -EINVAL;
1948
1949 value = simple_strtoul(buffer, NULL, 10);
1950 mutex_lock(&spic_dev.lock);
1951 __sony_pic_set_wwanpower(value);
1952 mutex_unlock(&spic_dev.lock);
1953
1954 return count;
1955}
1956
1957static ssize_t sony_pic_wwanpower_show(struct device *dev,
1958 struct device_attribute *attr, char *buffer)
1959{
1960 ssize_t count;
1961 mutex_lock(&spic_dev.lock);
1962 count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.wwan_power);
1963 mutex_unlock(&spic_dev.lock);
1964 return count;
1965}
1966
1967
1968static void __sony_pic_set_bluetoothpower(u8 state)
1969{
1970 state = !!state;
1971 if (spic_dev.bluetooth_power == state)
1972 return;
1973 sony_pic_call2(0x96, state);
1974 sony_pic_call1(0x82);
1975 spic_dev.bluetooth_power = state;
1976}
1977
1978static ssize_t sony_pic_bluetoothpower_store(struct device *dev,
1979 struct device_attribute *attr,
1980 const char *buffer, size_t count)
1981{
1982 unsigned long value;
1983 if (count > 31)
1984 return -EINVAL;
1985
1986 value = simple_strtoul(buffer, NULL, 10);
1987 mutex_lock(&spic_dev.lock);
1988 __sony_pic_set_bluetoothpower(value);
1989 mutex_unlock(&spic_dev.lock);
1990
1991 return count;
1992}
1993
1994static ssize_t sony_pic_bluetoothpower_show(struct device *dev,
1995 struct device_attribute *attr, char *buffer)
1996{
1997 ssize_t count = 0;
1998 mutex_lock(&spic_dev.lock);
1999 count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power);
2000 mutex_unlock(&spic_dev.lock);
2001 return count;
2002}
2003
2004
2005
2006#define SONY_PIC_FAN0_STATUS 0x93
2007static int sony_pic_set_fanspeed(unsigned long value)
2008{
2009 return ec_write(SONY_PIC_FAN0_STATUS, value);
2010}
2011
2012static int sony_pic_get_fanspeed(u8 *value)
2013{
2014 return ec_read(SONY_PIC_FAN0_STATUS, value);
2015}
2016
2017static ssize_t sony_pic_fanspeed_store(struct device *dev,
2018 struct device_attribute *attr,
2019 const char *buffer, size_t count)
2020{
2021 unsigned long value;
2022 if (count > 31)
2023 return -EINVAL;
2024
2025 value = simple_strtoul(buffer, NULL, 10);
2026 if (sony_pic_set_fanspeed(value))
2027 return -EIO;
2028
2029 return count;
2030}
2031
2032static ssize_t sony_pic_fanspeed_show(struct device *dev,
2033 struct device_attribute *attr, char *buffer)
2034{
2035 u8 value = 0;
2036 if (sony_pic_get_fanspeed(&value))
2037 return -EIO;
2038
2039 return snprintf(buffer, PAGE_SIZE, "%d\n", value);
2040}
2041
2042#define SPIC_ATTR(_name, _mode) \
2043struct device_attribute spic_attr_##_name = __ATTR(_name, \
2044 _mode, sony_pic_## _name ##_show, \
2045 sony_pic_## _name ##_store)
2046
2047static SPIC_ATTR(bluetoothpower, 0644);
2048static SPIC_ATTR(wwanpower, 0644);
2049static SPIC_ATTR(fanspeed, 0644);
2050
2051static struct attribute *spic_attributes[] = {
2052 &spic_attr_bluetoothpower.attr,
2053 &spic_attr_wwanpower.attr,
2054 &spic_attr_fanspeed.attr,
2055 NULL
2056};
2057
2058static struct attribute_group spic_attribute_group = {
2059 .attrs = spic_attributes
2060};
2061
2062
2063#ifdef CONFIG_SONYPI_COMPAT
2064
2065
2066#define SONYPI_BAT_FLAGS 0x81
2067#define SONYPI_LCD_LIGHT 0x96
2068#define SONYPI_BAT1_PCTRM 0xa0
2069#define SONYPI_BAT1_LEFT 0xa2
2070#define SONYPI_BAT1_MAXRT 0xa4
2071#define SONYPI_BAT2_PCTRM 0xa8
2072#define SONYPI_BAT2_LEFT 0xaa
2073#define SONYPI_BAT2_MAXRT 0xac
2074#define SONYPI_BAT1_MAXTK 0xb0
2075#define SONYPI_BAT1_FULL 0xb2
2076#define SONYPI_BAT2_MAXTK 0xb8
2077#define SONYPI_BAT2_FULL 0xba
2078#define SONYPI_TEMP_STATUS 0xC1
2079
2080struct sonypi_compat_s {
2081 struct fasync_struct *fifo_async;
2082 struct kfifo *fifo;
2083 spinlock_t fifo_lock;
2084 wait_queue_head_t fifo_proc_list;
2085 atomic_t open_count;
2086};
2087static struct sonypi_compat_s sonypi_compat = {
2088 .open_count = ATOMIC_INIT(0),
2089};
2090
2091static int sonypi_misc_fasync(int fd, struct file *filp, int on)
2092{
2093 return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
2094}
2095
2096static int sonypi_misc_release(struct inode *inode, struct file *file)
2097{
2098 atomic_dec(&sonypi_compat.open_count);
2099 return 0;
2100}
2101
2102static int sonypi_misc_open(struct inode *inode, struct file *file)
2103{
2104
2105 unsigned long flags;
2106
2107 spin_lock_irqsave(sonypi_compat.fifo->lock, flags);
2108
2109 if (atomic_inc_return(&sonypi_compat.open_count) == 1)
2110 __kfifo_reset(sonypi_compat.fifo);
2111
2112 spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags);
2113
2114 return 0;
2115}
2116
2117static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
2118 size_t count, loff_t *pos)
2119{
2120 ssize_t ret;
2121 unsigned char c;
2122
2123 if ((kfifo_len(sonypi_compat.fifo) == 0) &&
2124 (file->f_flags & O_NONBLOCK))
2125 return -EAGAIN;
2126
2127 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
2128 kfifo_len(sonypi_compat.fifo) != 0);
2129 if (ret)
2130 return ret;
2131
2132 while (ret < count &&
2133 (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) {
2134 if (put_user(c, buf++))
2135 return -EFAULT;
2136 ret++;
2137 }
2138
2139 if (ret > 0) {
2140 struct inode *inode = file->f_path.dentry->d_inode;
2141 inode->i_atime = current_fs_time(inode->i_sb);
2142 }
2143
2144 return ret;
2145}
2146
2147static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
2148{
2149 poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
2150 if (kfifo_len(sonypi_compat.fifo))
2151 return POLLIN | POLLRDNORM;
2152 return 0;
2153}
2154
2155static int ec_read16(u8 addr, u16 *value)
2156{
2157 u8 val_lb, val_hb;
2158 if (ec_read(addr, &val_lb))
2159 return -1;
2160 if (ec_read(addr + 1, &val_hb))
2161 return -1;
2162 *value = val_lb | (val_hb << 8);
2163 return 0;
2164}
2165
2166static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
2167 unsigned long arg)
2168{
2169 int ret = 0;
2170 void __user *argp = (void __user *)arg;
2171 u8 val8;
2172 u16 val16;
2173 int value;
2174
2175 mutex_lock(&spic_dev.lock);
2176 switch (cmd) {
2177 case SONYPI_IOCGBRT:
2178 if (sony_backlight_device == NULL) {
2179 ret = -EIO;
2180 break;
2181 }
2182 if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) {
2183 ret = -EIO;
2184 break;
2185 }
2186 val8 = ((value & 0xff) - 1) << 5;
2187 if (copy_to_user(argp, &val8, sizeof(val8)))
2188 ret = -EFAULT;
2189 break;
2190 case SONYPI_IOCSBRT:
2191 if (sony_backlight_device == NULL) {
2192 ret = -EIO;
2193 break;
2194 }
2195 if (copy_from_user(&val8, argp, sizeof(val8))) {
2196 ret = -EFAULT;
2197 break;
2198 }
2199 if (acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
2200 (val8 >> 5) + 1, NULL)) {
2201 ret = -EIO;
2202 break;
2203 }
2204
2205 sony_backlight_device->props.brightness =
2206 sony_backlight_get_brightness(sony_backlight_device);
2207 break;
2208 case SONYPI_IOCGBAT1CAP:
2209 if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
2210 ret = -EIO;
2211 break;
2212 }
2213 if (copy_to_user(argp, &val16, sizeof(val16)))
2214 ret = -EFAULT;
2215 break;
2216 case SONYPI_IOCGBAT1REM:
2217 if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
2218 ret = -EIO;
2219 break;
2220 }
2221 if (copy_to_user(argp, &val16, sizeof(val16)))
2222 ret = -EFAULT;
2223 break;
2224 case SONYPI_IOCGBAT2CAP:
2225 if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
2226 ret = -EIO;
2227 break;
2228 }
2229 if (copy_to_user(argp, &val16, sizeof(val16)))
2230 ret = -EFAULT;
2231 break;
2232 case SONYPI_IOCGBAT2REM:
2233 if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
2234 ret = -EIO;
2235 break;
2236 }
2237 if (copy_to_user(argp, &val16, sizeof(val16)))
2238 ret = -EFAULT;
2239 break;
2240 case SONYPI_IOCGBATFLAGS:
2241 if (ec_read(SONYPI_BAT_FLAGS, &val8)) {
2242 ret = -EIO;
2243 break;
2244 }
2245 val8 &= 0x07;
2246 if (copy_to_user(argp, &val8, sizeof(val8)))
2247 ret = -EFAULT;
2248 break;
2249 case SONYPI_IOCGBLUE:
2250 val8 = spic_dev.bluetooth_power;
2251 if (copy_to_user(argp, &val8, sizeof(val8)))
2252 ret = -EFAULT;
2253 break;
2254 case SONYPI_IOCSBLUE:
2255 if (copy_from_user(&val8, argp, sizeof(val8))) {
2256 ret = -EFAULT;
2257 break;
2258 }
2259 __sony_pic_set_bluetoothpower(val8);
2260 break;
2261
2262 case SONYPI_IOCGFAN:
2263 if (sony_pic_get_fanspeed(&val8)) {
2264 ret = -EIO;
2265 break;
2266 }
2267 if (copy_to_user(argp, &val8, sizeof(val8)))
2268 ret = -EFAULT;
2269 break;
2270 case SONYPI_IOCSFAN:
2271 if (copy_from_user(&val8, argp, sizeof(val8))) {
2272 ret = -EFAULT;
2273 break;
2274 }
2275 if (sony_pic_set_fanspeed(val8))
2276 ret = -EIO;
2277 break;
2278
2279 case SONYPI_IOCGTEMP:
2280 if (ec_read(SONYPI_TEMP_STATUS, &val8)) {
2281 ret = -EIO;
2282 break;
2283 }
2284 if (copy_to_user(argp, &val8, sizeof(val8)))
2285 ret = -EFAULT;
2286 break;
2287 default:
2288 ret = -EINVAL;
2289 }
2290 mutex_unlock(&spic_dev.lock);
2291 return ret;
2292}
2293
2294static const struct file_operations sonypi_misc_fops = {
2295 .owner = THIS_MODULE,
2296 .read = sonypi_misc_read,
2297 .poll = sonypi_misc_poll,
2298 .open = sonypi_misc_open,
2299 .release = sonypi_misc_release,
2300 .fasync = sonypi_misc_fasync,
2301 .unlocked_ioctl = sonypi_misc_ioctl,
2302};
2303
2304static struct miscdevice sonypi_misc_device = {
2305 .minor = MISC_DYNAMIC_MINOR,
2306 .name = "sonypi",
2307 .fops = &sonypi_misc_fops,
2308};
2309
2310static void sonypi_compat_report_event(u8 event)
2311{
2312 kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event));
2313 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
2314 wake_up_interruptible(&sonypi_compat.fifo_proc_list);
2315}
2316
2317static int sonypi_compat_init(void)
2318{
2319 int error;
2320
2321 spin_lock_init(&sonypi_compat.fifo_lock);
2322 sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
2323 &sonypi_compat.fifo_lock);
2324 if (IS_ERR(sonypi_compat.fifo)) {
2325 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
2326 return PTR_ERR(sonypi_compat.fifo);
2327 }
2328
2329 init_waitqueue_head(&sonypi_compat.fifo_proc_list);
2330
2331 if (minor != -1)
2332 sonypi_misc_device.minor = minor;
2333 error = misc_register(&sonypi_misc_device);
2334 if (error) {
2335 printk(KERN_ERR DRV_PFX "misc_register failed\n");
2336 goto err_free_kfifo;
2337 }
2338 if (minor == -1)
2339 printk(KERN_INFO DRV_PFX "device allocated minor is %d\n",
2340 sonypi_misc_device.minor);
2341
2342 return 0;
2343
2344err_free_kfifo:
2345 kfifo_free(sonypi_compat.fifo);
2346 return error;
2347}
2348
2349static void sonypi_compat_exit(void)
2350{
2351 misc_deregister(&sonypi_misc_device);
2352 kfifo_free(sonypi_compat.fifo);
2353}
2354#else
2355static int sonypi_compat_init(void) { return 0; }
2356static void sonypi_compat_exit(void) { }
2357static void sonypi_compat_report_event(u8 event) { }
2358#endif
2359
2360
2361
2362
2363static acpi_status
2364sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2365{
2366 u32 i;
2367 struct sony_pic_dev *dev = (struct sony_pic_dev *)context;
2368
2369 switch (resource->type) {
2370 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
2371 {
2372
2373 struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
2374 if (!ioport)
2375 return AE_ERROR;
2376
2377 list_add(&ioport->list, &dev->ioports);
2378 return AE_OK;
2379 }
2380
2381 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
2382
2383 return AE_OK;
2384
2385 case ACPI_RESOURCE_TYPE_IRQ:
2386 {
2387 struct acpi_resource_irq *p = &resource->data.irq;
2388 struct sony_pic_irq *interrupt = NULL;
2389 if (!p || !p->interrupt_count) {
2390
2391
2392
2393
2394 dprintk("Blank IRQ resource\n");
2395 return AE_OK;
2396 }
2397 for (i = 0; i < p->interrupt_count; i++) {
2398 if (!p->interrupts[i]) {
2399 printk(KERN_WARNING DRV_PFX
2400 "Invalid IRQ %d\n",
2401 p->interrupts[i]);
2402 continue;
2403 }
2404 interrupt = kzalloc(sizeof(*interrupt),
2405 GFP_KERNEL);
2406 if (!interrupt)
2407 return AE_ERROR;
2408
2409 list_add(&interrupt->list, &dev->interrupts);
2410 interrupt->irq.triggering = p->triggering;
2411 interrupt->irq.polarity = p->polarity;
2412 interrupt->irq.sharable = p->sharable;
2413 interrupt->irq.interrupt_count = 1;
2414 interrupt->irq.interrupts[0] = p->interrupts[i];
2415 }
2416 return AE_OK;
2417 }
2418 case ACPI_RESOURCE_TYPE_IO:
2419 {
2420 struct acpi_resource_io *io = &resource->data.io;
2421 struct sony_pic_ioport *ioport =
2422 list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
2423 if (!io) {
2424 dprintk("Blank IO resource\n");
2425 return AE_OK;
2426 }
2427
2428 if (!ioport->io1.minimum) {
2429 memcpy(&ioport->io1, io, sizeof(*io));
2430 dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
2431 ioport->io1.address_length);
2432 }
2433 else if (!ioport->io2.minimum) {
2434 memcpy(&ioport->io2, io, sizeof(*io));
2435 dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
2436 ioport->io2.address_length);
2437 }
2438 else {
2439 printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
2440 return AE_ERROR;
2441 }
2442 return AE_OK;
2443 }
2444 default:
2445 dprintk("Resource %d isn't an IRQ nor an IO port\n",
2446 resource->type);
2447
2448 case ACPI_RESOURCE_TYPE_END_TAG:
2449 return AE_OK;
2450 }
2451 return AE_CTRL_TERMINATE;
2452}
2453
2454static int sony_pic_possible_resources(struct acpi_device *device)
2455{
2456 int result = 0;
2457 acpi_status status = AE_OK;
2458
2459 if (!device)
2460 return -EINVAL;
2461
2462
2463
2464 dprintk("Evaluating _STA\n");
2465 result = acpi_bus_get_status(device);
2466 if (result) {
2467 printk(KERN_WARNING DRV_PFX "Unable to read status\n");
2468 goto end;
2469 }
2470
2471 if (!device->status.enabled)
2472 dprintk("Device disabled\n");
2473 else
2474 dprintk("Device enabled\n");
2475
2476
2477
2478
2479 dprintk("Evaluating %s\n", METHOD_NAME__PRS);
2480 status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
2481 sony_pic_read_possible_resource, &spic_dev);
2482 if (ACPI_FAILURE(status)) {
2483 printk(KERN_WARNING DRV_PFX
2484 "Failure evaluating %s\n",
2485 METHOD_NAME__PRS);
2486 result = -ENODEV;
2487 }
2488end:
2489 return result;
2490}
2491
2492
2493
2494
2495static int sony_pic_disable(struct acpi_device *device)
2496{
2497 acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL,
2498 NULL);
2499
2500 if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND)
2501 return -ENXIO;
2502
2503 dprintk("Device disabled\n");
2504 return 0;
2505}
2506
2507
2508
2509
2510
2511
2512
2513static int sony_pic_enable(struct acpi_device *device,
2514 struct sony_pic_ioport *ioport, struct sony_pic_irq *irq)
2515{
2516 acpi_status status;
2517 int result = 0;
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529 struct {
2530 struct acpi_resource res1;
2531 struct acpi_resource res2;
2532 struct acpi_resource res3;
2533 struct acpi_resource res4;
2534 } *resource;
2535 struct acpi_buffer buffer = { 0, NULL };
2536
2537 if (!ioport || !irq)
2538 return -EINVAL;
2539
2540
2541 resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
2542 if (!resource)
2543 return -ENOMEM;
2544
2545 buffer.length = sizeof(*resource) + 1;
2546 buffer.pointer = resource;
2547
2548
2549 if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
2550
2551
2552 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
2553 resource->res1.length = sizeof(struct acpi_resource);
2554 memcpy(&resource->res1.data.io, &ioport->io1,
2555 sizeof(struct acpi_resource_io));
2556
2557 resource->res2.type = ACPI_RESOURCE_TYPE_IO;
2558 resource->res2.length = sizeof(struct acpi_resource);
2559 memcpy(&resource->res2.data.io, &ioport->io2,
2560 sizeof(struct acpi_resource_io));
2561
2562
2563 resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
2564 resource->res3.length = sizeof(struct acpi_resource);
2565 memcpy(&resource->res3.data.irq, &irq->irq,
2566 sizeof(struct acpi_resource_irq));
2567
2568 resource->res3.data.irq.sharable = ACPI_SHARED;
2569
2570 resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
2571
2572 }
2573
2574 else {
2575
2576 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
2577 resource->res1.length = sizeof(struct acpi_resource);
2578 memcpy(&resource->res1.data.io, &ioport->io1,
2579 sizeof(struct acpi_resource_io));
2580
2581
2582 resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
2583 resource->res2.length = sizeof(struct acpi_resource);
2584 memcpy(&resource->res2.data.irq, &irq->irq,
2585 sizeof(struct acpi_resource_irq));
2586
2587 resource->res2.data.irq.sharable = ACPI_SHARED;
2588
2589 resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
2590 }
2591
2592
2593 dprintk("Evaluating _SRS\n");
2594 status = acpi_set_current_resources(device->handle, &buffer);
2595
2596
2597 if (ACPI_FAILURE(status)) {
2598 printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n");
2599 result = -ENODEV;
2600 goto end;
2601 }
2602
2603
2604 sony_pic_call1(0x82);
2605 sony_pic_call2(0x81, 0xff);
2606 sony_pic_call1(compat ? 0x92 : 0x82);
2607
2608end:
2609 kfree(resource);
2610 return result;
2611}
2612
2613
2614
2615
2616
2617
2618static irqreturn_t sony_pic_irq(int irq, void *dev_id)
2619{
2620 int i, j;
2621 u8 ev = 0;
2622 u8 data_mask = 0;
2623 u8 device_event = 0;
2624
2625 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
2626
2627 ev = inb_p(dev->cur_ioport->io1.minimum);
2628 if (dev->cur_ioport->io2.minimum)
2629 data_mask = inb_p(dev->cur_ioport->io2.minimum);
2630 else
2631 data_mask = inb_p(dev->cur_ioport->io1.minimum +
2632 dev->evport_offset);
2633
2634 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
2635 ev, data_mask, dev->cur_ioport->io1.minimum,
2636 dev->evport_offset);
2637
2638 if (ev == 0x00 || ev == 0xff)
2639 return IRQ_HANDLED;
2640
2641 for (i = 0; dev->event_types[i].mask; i++) {
2642
2643 if ((data_mask & dev->event_types[i].data) !=
2644 dev->event_types[i].data)
2645 continue;
2646
2647 if (!(mask & dev->event_types[i].mask))
2648 continue;
2649
2650 for (j = 0; dev->event_types[i].events[j].event; j++) {
2651 if (ev == dev->event_types[i].events[j].data) {
2652 device_event =
2653 dev->event_types[i].events[j].event;
2654 goto found;
2655 }
2656 }
2657 }
2658
2659
2660
2661 if (dev->handle_irq && dev->handle_irq(data_mask, ev) == 0)
2662 return IRQ_HANDLED;
2663
2664 dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
2665 ev, data_mask, dev->cur_ioport->io1.minimum,
2666 dev->evport_offset);
2667 return IRQ_HANDLED;
2668
2669found:
2670 sony_laptop_report_input_event(device_event);
2671 acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
2672 sonypi_compat_report_event(device_event);
2673
2674 return IRQ_HANDLED;
2675}
2676
2677
2678
2679
2680
2681
2682static int sony_pic_remove(struct acpi_device *device, int type)
2683{
2684 struct sony_pic_ioport *io, *tmp_io;
2685 struct sony_pic_irq *irq, *tmp_irq;
2686
2687 if (sony_pic_disable(device)) {
2688 printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
2689 return -ENXIO;
2690 }
2691
2692 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
2693 release_region(spic_dev.cur_ioport->io1.minimum,
2694 spic_dev.cur_ioport->io1.address_length);
2695 if (spic_dev.cur_ioport->io2.minimum)
2696 release_region(spic_dev.cur_ioport->io2.minimum,
2697 spic_dev.cur_ioport->io2.address_length);
2698
2699 sonypi_compat_exit();
2700
2701 sony_laptop_remove_input();
2702
2703
2704 sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
2705 sony_pf_remove();
2706
2707 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
2708 list_del(&io->list);
2709 kfree(io);
2710 }
2711 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
2712 list_del(&irq->list);
2713 kfree(irq);
2714 }
2715 spic_dev.cur_ioport = NULL;
2716 spic_dev.cur_irq = NULL;
2717
2718 dprintk(SONY_PIC_DRIVER_NAME " removed.\n");
2719 return 0;
2720}
2721
2722static int sony_pic_add(struct acpi_device *device)
2723{
2724 int result;
2725 struct sony_pic_ioport *io, *tmp_io;
2726 struct sony_pic_irq *irq, *tmp_irq;
2727
2728 printk(KERN_INFO DRV_PFX "%s v%s.\n",
2729 SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
2730
2731 spic_dev.acpi_dev = device;
2732 strcpy(acpi_device_class(device), "sony/hotkey");
2733 sony_pic_detect_device_type(&spic_dev);
2734 mutex_init(&spic_dev.lock);
2735
2736
2737 result = sony_pic_possible_resources(device);
2738 if (result) {
2739 printk(KERN_ERR DRV_PFX
2740 "Unable to read possible resources.\n");
2741 goto err_free_resources;
2742 }
2743
2744
2745 result = sony_laptop_setup_input(device);
2746 if (result) {
2747 printk(KERN_ERR DRV_PFX
2748 "Unable to create input devices.\n");
2749 goto err_free_resources;
2750 }
2751
2752 if (sonypi_compat_init())
2753 goto err_remove_input;
2754
2755
2756 list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
2757 if (request_region(io->io1.minimum, io->io1.address_length,
2758 "Sony Programable I/O Device")) {
2759 dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
2760 io->io1.minimum, io->io1.maximum,
2761 io->io1.address_length);
2762
2763 if (io->io2.minimum) {
2764 if (request_region(io->io2.minimum,
2765 io->io2.address_length,
2766 "Sony Programable I/O Device")) {
2767 dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
2768 io->io2.minimum, io->io2.maximum,
2769 io->io2.address_length);
2770 spic_dev.cur_ioport = io;
2771 break;
2772 }
2773 else {
2774 dprintk("Unable to get I/O port2: "
2775 "0x%.4x (0x%.4x) + 0x%.2x\n",
2776 io->io2.minimum, io->io2.maximum,
2777 io->io2.address_length);
2778 release_region(io->io1.minimum,
2779 io->io1.address_length);
2780 }
2781 }
2782 else {
2783 spic_dev.cur_ioport = io;
2784 break;
2785 }
2786 }
2787 }
2788 if (!spic_dev.cur_ioport) {
2789 printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
2790 result = -ENODEV;
2791 goto err_remove_compat;
2792 }
2793
2794
2795 list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
2796 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
2797 IRQF_DISABLED, "sony-laptop", &spic_dev)) {
2798 dprintk("IRQ: %d - triggering: %d - "
2799 "polarity: %d - shr: %d\n",
2800 irq->irq.interrupts[0],
2801 irq->irq.triggering,
2802 irq->irq.polarity,
2803 irq->irq.sharable);
2804 spic_dev.cur_irq = irq;
2805 break;
2806 }
2807 }
2808 if (!spic_dev.cur_irq) {
2809 printk(KERN_ERR DRV_PFX "Failed to request_irq.\n");
2810 result = -ENODEV;
2811 goto err_release_region;
2812 }
2813
2814
2815 result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
2816 if (result) {
2817 printk(KERN_ERR DRV_PFX "Couldn't enable device.\n");
2818 goto err_free_irq;
2819 }
2820
2821 spic_dev.bluetooth_power = -1;
2822
2823 result = sony_pf_add();
2824 if (result)
2825 goto err_disable_device;
2826
2827 result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
2828 if (result)
2829 goto err_remove_pf;
2830
2831 return 0;
2832
2833err_remove_pf:
2834 sony_pf_remove();
2835
2836err_disable_device:
2837 sony_pic_disable(device);
2838
2839err_free_irq:
2840 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
2841
2842err_release_region:
2843 release_region(spic_dev.cur_ioport->io1.minimum,
2844 spic_dev.cur_ioport->io1.address_length);
2845 if (spic_dev.cur_ioport->io2.minimum)
2846 release_region(spic_dev.cur_ioport->io2.minimum,
2847 spic_dev.cur_ioport->io2.address_length);
2848
2849err_remove_compat:
2850 sonypi_compat_exit();
2851
2852err_remove_input:
2853 sony_laptop_remove_input();
2854
2855err_free_resources:
2856 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
2857 list_del(&io->list);
2858 kfree(io);
2859 }
2860 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
2861 list_del(&irq->list);
2862 kfree(irq);
2863 }
2864 spic_dev.cur_ioport = NULL;
2865 spic_dev.cur_irq = NULL;
2866
2867 return result;
2868}
2869
2870static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
2871{
2872 if (sony_pic_disable(device))
2873 return -ENXIO;
2874 return 0;
2875}
2876
2877static int sony_pic_resume(struct acpi_device *device)
2878{
2879 sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
2880 return 0;
2881}
2882
2883static const struct acpi_device_id sony_pic_device_ids[] = {
2884 {SONY_PIC_HID, 0},
2885 {"", 0},
2886};
2887
2888static struct acpi_driver sony_pic_driver = {
2889 .name = SONY_PIC_DRIVER_NAME,
2890 .class = SONY_PIC_CLASS,
2891 .ids = sony_pic_device_ids,
2892 .owner = THIS_MODULE,
2893 .ops = {
2894 .add = sony_pic_add,
2895 .remove = sony_pic_remove,
2896 .suspend = sony_pic_suspend,
2897 .resume = sony_pic_resume,
2898 },
2899};
2900
2901static struct dmi_system_id __initdata sonypi_dmi_table[] = {
2902 {
2903 .ident = "Sony Vaio",
2904 .matches = {
2905 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2906 DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"),
2907 },
2908 },
2909 {
2910 .ident = "Sony Vaio",
2911 .matches = {
2912 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2913 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
2914 },
2915 },
2916 { }
2917};
2918
2919static int __init sony_laptop_init(void)
2920{
2921 int result;
2922
2923 if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
2924 result = acpi_bus_register_driver(&sony_pic_driver);
2925 if (result) {
2926 printk(KERN_ERR DRV_PFX
2927 "Unable to register SPIC driver.");
2928 goto out;
2929 }
2930 spic_drv_registered = 1;
2931 }
2932
2933 result = acpi_bus_register_driver(&sony_nc_driver);
2934 if (result) {
2935 printk(KERN_ERR DRV_PFX "Unable to register SNC driver.");
2936 goto out_unregister_pic;
2937 }
2938
2939 return 0;
2940
2941out_unregister_pic:
2942 if (spic_drv_registered)
2943 acpi_bus_unregister_driver(&sony_pic_driver);
2944out:
2945 return result;
2946}
2947
2948static void __exit sony_laptop_exit(void)
2949{
2950 acpi_bus_unregister_driver(&sony_nc_driver);
2951 if (spic_drv_registered)
2952 acpi_bus_unregister_driver(&sony_pic_driver);
2953}
2954
2955module_init(sony_laptop_init);
2956module_exit(sony_laptop_exit);
2957