1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#define IBM_VERSION "0.17"
25#define TPACPI_SYSFS_VERSION 0x020000
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85#include "thinkpad_acpi.h"
86
87MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
88MODULE_DESCRIPTION(IBM_DESC);
89MODULE_VERSION(IBM_VERSION);
90MODULE_LICENSE("GPL");
91
92
93MODULE_ALIAS("ibm_acpi");
94
95
96
97
98
99
100
101
102
103
104#define IBM_BIOS_MODULE_ALIAS(__type) \
105 MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW")
106
107
108MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
109MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
110
111
112
113
114IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]");
115IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
116IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
117
118#define __unused __attribute__ ((unused))
119
120static enum {
121 TPACPI_LIFE_INIT = 0,
122 TPACPI_LIFE_RUNNING,
123 TPACPI_LIFE_EXITING,
124} tpacpi_lifecycle;
125
126
127
128
129
130
131
132
133
134
135
136
137
138static acpi_handle root_handle;
139
140#define IBM_HANDLE(object, parent, paths...) \
141 static acpi_handle object##_handle; \
142 static acpi_handle *object##_parent = &parent##_handle; \
143 static char *object##_path; \
144 static char *object##_paths[] = { paths }
145
146IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",
147 "\\_SB.PCI.ISA.EC",
148 "\\_SB.PCI0.ISA0.EC0",
149 "\\_SB.PCI0.ISA.EC",
150 "\\_SB.PCI0.AD4S.EC0",
151 "\\_SB.PCI0.ICH3.EC0",
152 "\\_SB.PCI0.LPC.EC",
153 );
154
155IBM_HANDLE(ecrd, ec, "ECRD");
156IBM_HANDLE(ecwr, ec, "ECWR");
157
158
159
160
161
162
163IBM_HANDLE(cmos, root, "\\UCMS",
164 "\\CMOS",
165 "\\CMS",
166 );
167
168IBM_HANDLE(hkey, ec, "\\_SB.HKEY",
169 "^HKEY",
170 "HKEY",
171 );
172
173
174
175
176
177
178static int acpi_evalf(acpi_handle handle,
179 void *res, char *method, char *fmt, ...)
180{
181 char *fmt0 = fmt;
182 struct acpi_object_list params;
183 union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
184 struct acpi_buffer result, *resultp;
185 union acpi_object out_obj;
186 acpi_status status;
187 va_list ap;
188 char res_type;
189 int success;
190 int quiet;
191
192 if (!*fmt) {
193 printk(IBM_ERR "acpi_evalf() called with empty format\n");
194 return 0;
195 }
196
197 if (*fmt == 'q') {
198 quiet = 1;
199 fmt++;
200 } else
201 quiet = 0;
202
203 res_type = *(fmt++);
204
205 params.count = 0;
206 params.pointer = &in_objs[0];
207
208 va_start(ap, fmt);
209 while (*fmt) {
210 char c = *(fmt++);
211 switch (c) {
212 case 'd':
213 in_objs[params.count].integer.value = va_arg(ap, int);
214 in_objs[params.count++].type = ACPI_TYPE_INTEGER;
215 break;
216
217 default:
218 printk(IBM_ERR "acpi_evalf() called "
219 "with invalid format character '%c'\n", c);
220 return 0;
221 }
222 }
223 va_end(ap);
224
225 if (res_type != 'v') {
226 result.length = sizeof(out_obj);
227 result.pointer = &out_obj;
228 resultp = &result;
229 } else
230 resultp = NULL;
231
232 status = acpi_evaluate_object(handle, method, ¶ms, resultp);
233
234 switch (res_type) {
235 case 'd':
236 if (res)
237 *(int *)res = out_obj.integer.value;
238 success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
239 break;
240 case 'v':
241 success = status == AE_OK;
242 break;
243
244 default:
245 printk(IBM_ERR "acpi_evalf() called "
246 "with invalid format character '%c'\n", res_type);
247 return 0;
248 }
249
250 if (!success && !quiet)
251 printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
252 method, fmt0, status);
253
254 return success;
255}
256
257static void __unused acpi_print_int(acpi_handle handle, char *method)
258{
259 int i;
260
261 if (acpi_evalf(handle, &i, method, "d"))
262 printk(IBM_INFO "%s = 0x%x\n", method, i);
263 else
264 printk(IBM_ERR "error calling %s\n", method);
265}
266
267static int acpi_ec_read(int i, u8 * p)
268{
269 int v;
270
271 if (ecrd_handle) {
272 if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
273 return 0;
274 *p = v;
275 } else {
276 if (ec_read(i, p) < 0)
277 return 0;
278 }
279
280 return 1;
281}
282
283static int acpi_ec_write(int i, u8 v)
284{
285 if (ecwr_handle) {
286 if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
287 return 0;
288 } else {
289 if (ec_write(i, v) < 0)
290 return 0;
291 }
292
293 return 1;
294}
295
296static int _sta(acpi_handle handle)
297{
298 int status;
299
300 if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
301 status = 0;
302
303 return status;
304}
305
306static int issue_thinkpad_cmos_command(int cmos_cmd)
307{
308 if (!cmos_handle)
309 return -ENXIO;
310
311 if (!acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd))
312 return -EIO;
313
314 return 0;
315}
316
317
318
319
320
321static void drv_acpi_handle_init(char *name,
322 acpi_handle *handle, acpi_handle parent,
323 char **paths, int num_paths, char **path)
324{
325 int i;
326 acpi_status status;
327
328 vdbg_printk(TPACPI_DBG_INIT, "trying to locate ACPI handle for %s\n",
329 name);
330
331 for (i = 0; i < num_paths; i++) {
332 status = acpi_get_handle(parent, paths[i], handle);
333 if (ACPI_SUCCESS(status)) {
334 *path = paths[i];
335 dbg_printk(TPACPI_DBG_INIT,
336 "Found ACPI handle %s for %s\n",
337 *path, name);
338 return;
339 }
340 }
341
342 vdbg_printk(TPACPI_DBG_INIT, "ACPI handle for %s not found\n",
343 name);
344 *handle = NULL;
345}
346
347static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data)
348{
349 struct ibm_struct *ibm = data;
350
351 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
352 return;
353
354 if (!ibm || !ibm->acpi || !ibm->acpi->notify)
355 return;
356
357 ibm->acpi->notify(ibm, event);
358}
359
360static int __init setup_acpi_notify(struct ibm_struct *ibm)
361{
362 acpi_status status;
363 int rc;
364
365 BUG_ON(!ibm->acpi);
366
367 if (!*ibm->acpi->handle)
368 return 0;
369
370 vdbg_printk(TPACPI_DBG_INIT,
371 "setting up ACPI notify for %s\n", ibm->name);
372
373 rc = acpi_bus_get_device(*ibm->acpi->handle, &ibm->acpi->device);
374 if (rc < 0) {
375 printk(IBM_ERR "acpi_bus_get_device(%s) failed: %d\n",
376 ibm->name, rc);
377 return -ENODEV;
378 }
379
380 acpi_driver_data(ibm->acpi->device) = ibm;
381 sprintf(acpi_device_class(ibm->acpi->device), "%s/%s",
382 IBM_ACPI_EVENT_PREFIX,
383 ibm->name);
384
385 status = acpi_install_notify_handler(*ibm->acpi->handle,
386 ibm->acpi->type, dispatch_acpi_notify, ibm);
387 if (ACPI_FAILURE(status)) {
388 if (status == AE_ALREADY_EXISTS) {
389 printk(IBM_NOTICE "another device driver is already handling %s events\n",
390 ibm->name);
391 } else {
392 printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
393 ibm->name, status);
394 }
395 return -ENODEV;
396 }
397 ibm->flags.acpi_notify_installed = 1;
398 return 0;
399}
400
401static int __init tpacpi_device_add(struct acpi_device *device)
402{
403 return 0;
404}
405
406static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
407{
408 int rc;
409
410 dbg_printk(TPACPI_DBG_INIT,
411 "registering %s as an ACPI driver\n", ibm->name);
412
413 BUG_ON(!ibm->acpi);
414
415 ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
416 if (!ibm->acpi->driver) {
417 printk(IBM_ERR "kzalloc(ibm->driver) failed\n");
418 return -ENOMEM;
419 }
420
421 sprintf(ibm->acpi->driver->name, "%s_%s", IBM_NAME, ibm->name);
422 ibm->acpi->driver->ids = ibm->acpi->hid;
423
424 ibm->acpi->driver->ops.add = &tpacpi_device_add;
425
426 rc = acpi_bus_register_driver(ibm->acpi->driver);
427 if (rc < 0) {
428 printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
429 ibm->name, rc);
430 kfree(ibm->acpi->driver);
431 ibm->acpi->driver = NULL;
432 } else if (!rc)
433 ibm->flags.acpi_driver_registered = 1;
434
435 return rc;
436}
437
438
439
440
441
442
443
444
445
446
447static int dispatch_procfs_read(char *page, char **start, off_t off,
448 int count, int *eof, void *data)
449{
450 struct ibm_struct *ibm = data;
451 int len;
452
453 if (!ibm || !ibm->read)
454 return -EINVAL;
455
456 len = ibm->read(page);
457 if (len < 0)
458 return len;
459
460 if (len <= off + count)
461 *eof = 1;
462 *start = page + off;
463 len -= off;
464 if (len > count)
465 len = count;
466 if (len < 0)
467 len = 0;
468
469 return len;
470}
471
472static int dispatch_procfs_write(struct file *file,
473 const char __user * userbuf,
474 unsigned long count, void *data)
475{
476 struct ibm_struct *ibm = data;
477 char *kernbuf;
478 int ret;
479
480 if (!ibm || !ibm->write)
481 return -EINVAL;
482
483 kernbuf = kmalloc(count + 2, GFP_KERNEL);
484 if (!kernbuf)
485 return -ENOMEM;
486
487 if (copy_from_user(kernbuf, userbuf, count)) {
488 kfree(kernbuf);
489 return -EFAULT;
490 }
491
492 kernbuf[count] = 0;
493 strcat(kernbuf, ",");
494 ret = ibm->write(kernbuf);
495 if (ret == 0)
496 ret = count;
497
498 kfree(kernbuf);
499
500 return ret;
501}
502
503static char *next_cmd(char **cmds)
504{
505 char *start = *cmds;
506 char *end;
507
508 while ((end = strchr(start, ',')) && end == start)
509 start = end + 1;
510
511 if (!end)
512 return NULL;
513
514 *end = 0;
515 *cmds = end + 1;
516 return start;
517}
518
519
520
521
522
523
524
525
526
527
528static struct platform_device *tpacpi_pdev;
529static struct platform_device *tpacpi_sensors_pdev;
530static struct device *tpacpi_hwmon;
531static struct input_dev *tpacpi_inputdev;
532static struct mutex tpacpi_inputdev_send_mutex;
533
534
535static int tpacpi_resume_handler(struct platform_device *pdev)
536{
537 struct ibm_struct *ibm, *itmp;
538
539 list_for_each_entry_safe(ibm, itmp,
540 &tpacpi_all_drivers,
541 all_drivers) {
542 if (ibm->resume)
543 (ibm->resume)();
544 }
545
546 return 0;
547}
548
549static struct platform_driver tpacpi_pdriver = {
550 .driver = {
551 .name = IBM_DRVR_NAME,
552 .owner = THIS_MODULE,
553 },
554 .resume = tpacpi_resume_handler,
555};
556
557static struct platform_driver tpacpi_hwmon_pdriver = {
558 .driver = {
559 .name = IBM_HWMON_DRVR_NAME,
560 .owner = THIS_MODULE,
561 },
562};
563
564
565
566
567
568
569static ssize_t tpacpi_driver_interface_version_show(
570 struct device_driver *drv,
571 char *buf)
572{
573 return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION);
574}
575
576static DRIVER_ATTR(interface_version, S_IRUGO,
577 tpacpi_driver_interface_version_show, NULL);
578
579
580static ssize_t tpacpi_driver_debug_show(struct device_driver *drv,
581 char *buf)
582{
583 return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level);
584}
585
586static ssize_t tpacpi_driver_debug_store(struct device_driver *drv,
587 const char *buf, size_t count)
588{
589 unsigned long t;
590
591 if (parse_strtoul(buf, 0xffff, &t))
592 return -EINVAL;
593
594 dbg_level = t;
595
596 return count;
597}
598
599static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
600 tpacpi_driver_debug_show, tpacpi_driver_debug_store);
601
602
603static ssize_t tpacpi_driver_version_show(struct device_driver *drv,
604 char *buf)
605{
606 return snprintf(buf, PAGE_SIZE, "%s v%s\n", IBM_DESC, IBM_VERSION);
607}
608
609static DRIVER_ATTR(version, S_IRUGO,
610 tpacpi_driver_version_show, NULL);
611
612
613
614static struct driver_attribute* tpacpi_driver_attributes[] = {
615 &driver_attr_debug_level, &driver_attr_version,
616 &driver_attr_interface_version,
617};
618
619static int __init tpacpi_create_driver_attributes(struct device_driver *drv)
620{
621 int i, res;
622
623 i = 0;
624 res = 0;
625 while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) {
626 res = driver_create_file(drv, tpacpi_driver_attributes[i]);
627 i++;
628 }
629
630 return res;
631}
632
633static void tpacpi_remove_driver_attributes(struct device_driver *drv)
634{
635 int i;
636
637 for(i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
638 driver_remove_file(drv, tpacpi_driver_attributes[i]);
639}
640
641
642
643
644
645struct attribute_set_obj {
646 struct attribute_set s;
647 struct attribute *a;
648} __attribute__((packed));
649
650static struct attribute_set *create_attr_set(unsigned int max_members,
651 const char* name)
652{
653 struct attribute_set_obj *sobj;
654
655 if (max_members == 0)
656 return NULL;
657
658
659 sobj = kzalloc(sizeof(struct attribute_set_obj) +
660 max_members * sizeof(struct attribute *),
661 GFP_KERNEL);
662 if (!sobj)
663 return NULL;
664 sobj->s.max_members = max_members;
665 sobj->s.group.attrs = &sobj->a;
666 sobj->s.group.name = name;
667
668 return &sobj->s;
669}
670
671
672static int add_to_attr_set(struct attribute_set* s, struct attribute *attr)
673{
674 if (!s || !attr)
675 return -EINVAL;
676
677 if (s->members >= s->max_members)
678 return -ENOMEM;
679
680 s->group.attrs[s->members] = attr;
681 s->members++;
682
683 return 0;
684}
685
686static int add_many_to_attr_set(struct attribute_set* s,
687 struct attribute **attr,
688 unsigned int count)
689{
690 int i, res;
691
692 for (i = 0; i < count; i++) {
693 res = add_to_attr_set(s, attr[i]);
694 if (res)
695 return res;
696 }
697
698 return 0;
699}
700
701static void delete_attr_set(struct attribute_set* s, struct kobject *kobj)
702{
703 sysfs_remove_group(kobj, &s->group);
704 destroy_attr_set(s);
705}
706
707static int parse_strtoul(const char *buf,
708 unsigned long max, unsigned long *value)
709{
710 char *endp;
711
712 while (*buf && isspace(*buf))
713 buf++;
714 *value = simple_strtoul(buf, &endp, 0);
715 while (*endp && isspace(*endp))
716 endp++;
717 if (*endp || *value > max)
718 return -EINVAL;
719
720 return 0;
721}
722
723
724
725
726
727
728
729
730
731
732
733
734
735static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
736{
737 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
738 printk(IBM_INFO "%s\n", IBM_URL);
739
740 printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n",
741 (thinkpad_id.bios_version_str) ?
742 thinkpad_id.bios_version_str : "unknown",
743 (thinkpad_id.ec_version_str) ?
744 thinkpad_id.ec_version_str : "unknown");
745
746 if (thinkpad_id.vendor && thinkpad_id.model_str)
747 printk(IBM_INFO "%s %s\n",
748 (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
749 "IBM" : ((thinkpad_id.vendor ==
750 PCI_VENDOR_ID_LENOVO) ?
751 "Lenovo" : "Unknown vendor"),
752 thinkpad_id.model_str);
753
754 return 0;
755}
756
757static int thinkpad_acpi_driver_read(char *p)
758{
759 int len = 0;
760
761 len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC);
762 len += sprintf(p + len, "version:\t%s\n", IBM_VERSION);
763
764 return len;
765}
766
767static struct ibm_struct thinkpad_acpi_driver_data = {
768 .name = "driver",
769 .read = thinkpad_acpi_driver_read,
770};
771
772
773
774
775
776static int hotkey_orig_status;
777static u32 hotkey_orig_mask;
778static u32 hotkey_all_mask;
779static u32 hotkey_reserved_mask;
780
781static u16 *hotkey_keycode_map;
782
783static struct attribute_set *hotkey_dev_attributes;
784
785static int hotkey_get_wlsw(int *status)
786{
787 if (!acpi_evalf(hkey_handle, status, "WLSW", "d"))
788 return -EIO;
789 return 0;
790}
791
792
793static ssize_t hotkey_enable_show(struct device *dev,
794 struct device_attribute *attr,
795 char *buf)
796{
797 int res, status;
798 u32 mask;
799
800 res = hotkey_get(&status, &mask);
801 if (res)
802 return res;
803
804 return snprintf(buf, PAGE_SIZE, "%d\n", status);
805}
806
807static ssize_t hotkey_enable_store(struct device *dev,
808 struct device_attribute *attr,
809 const char *buf, size_t count)
810{
811 unsigned long t;
812 int res, status;
813 u32 mask;
814
815 if (parse_strtoul(buf, 1, &t))
816 return -EINVAL;
817
818 res = hotkey_get(&status, &mask);
819 if (!res)
820 res = hotkey_set(t, mask);
821
822 return (res) ? res : count;
823}
824
825static struct device_attribute dev_attr_hotkey_enable =
826 __ATTR(hotkey_enable, S_IWUSR | S_IRUGO,
827 hotkey_enable_show, hotkey_enable_store);
828
829
830static ssize_t hotkey_mask_show(struct device *dev,
831 struct device_attribute *attr,
832 char *buf)
833{
834 int res, status;
835 u32 mask;
836
837 res = hotkey_get(&status, &mask);
838 if (res)
839 return res;
840
841 return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask);
842}
843
844static ssize_t hotkey_mask_store(struct device *dev,
845 struct device_attribute *attr,
846 const char *buf, size_t count)
847{
848 unsigned long t;
849 int res, status;
850 u32 mask;
851
852 if (parse_strtoul(buf, 0xffffffffUL, &t))
853 return -EINVAL;
854
855 res = hotkey_get(&status, &mask);
856 if (!res)
857 hotkey_set(status, t);
858
859 return (res) ? res : count;
860}
861
862static struct device_attribute dev_attr_hotkey_mask =
863 __ATTR(hotkey_mask, S_IWUSR | S_IRUGO,
864 hotkey_mask_show, hotkey_mask_store);
865
866
867static ssize_t hotkey_bios_enabled_show(struct device *dev,
868 struct device_attribute *attr,
869 char *buf)
870{
871 return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status);
872}
873
874static struct device_attribute dev_attr_hotkey_bios_enabled =
875 __ATTR(hotkey_bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
876
877
878static ssize_t hotkey_bios_mask_show(struct device *dev,
879 struct device_attribute *attr,
880 char *buf)
881{
882 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask);
883}
884
885static struct device_attribute dev_attr_hotkey_bios_mask =
886 __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
887
888
889static ssize_t hotkey_all_mask_show(struct device *dev,
890 struct device_attribute *attr,
891 char *buf)
892{
893 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask);
894}
895
896static struct device_attribute dev_attr_hotkey_all_mask =
897 __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL);
898
899
900static ssize_t hotkey_recommended_mask_show(struct device *dev,
901 struct device_attribute *attr,
902 char *buf)
903{
904 return snprintf(buf, PAGE_SIZE, "0x%08x\n",
905 hotkey_all_mask & ~hotkey_reserved_mask);
906}
907
908static struct device_attribute dev_attr_hotkey_recommended_mask =
909 __ATTR(hotkey_recommended_mask, S_IRUGO,
910 hotkey_recommended_mask_show, NULL);
911
912
913static ssize_t hotkey_radio_sw_show(struct device *dev,
914 struct device_attribute *attr,
915 char *buf)
916{
917 int res, s;
918 res = hotkey_get_wlsw(&s);
919 if (res < 0)
920 return res;
921
922 return snprintf(buf, PAGE_SIZE, "%d\n", !!s);
923}
924
925static struct device_attribute dev_attr_hotkey_radio_sw =
926 __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);
927
928
929static ssize_t hotkey_report_mode_show(struct device *dev,
930 struct device_attribute *attr,
931 char *buf)
932{
933 return snprintf(buf, PAGE_SIZE, "%d\n",
934 (hotkey_report_mode != 0) ? hotkey_report_mode : 1);
935}
936
937static struct device_attribute dev_attr_hotkey_report_mode =
938 __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
939
940
941
942static struct attribute *hotkey_attributes[] __initdata = {
943 &dev_attr_hotkey_enable.attr,
944 &dev_attr_hotkey_report_mode.attr,
945};
946
947static struct attribute *hotkey_mask_attributes[] __initdata = {
948 &dev_attr_hotkey_mask.attr,
949 &dev_attr_hotkey_bios_enabled.attr,
950 &dev_attr_hotkey_bios_mask.attr,
951 &dev_attr_hotkey_all_mask.attr,
952 &dev_attr_hotkey_recommended_mask.attr,
953};
954
955static int __init hotkey_init(struct ibm_init_struct *iibm)
956{
957
958 static u16 ibm_keycode_map[] __initdata = {
959
960 KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP,
961 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
962 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
963
964 KEY_UNKNOWN,
965 KEY_UNKNOWN,
966 KEY_UNKNOWN,
967 KEY_RESERVED,
968
969 KEY_RESERVED,
970 KEY_RESERVED,
971 KEY_UNKNOWN,
972 KEY_ZOOM,
973 KEY_RESERVED,
974 KEY_RESERVED,
975 KEY_RESERVED,
976 KEY_VENDOR,
977
978 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
979 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
980 };
981 static u16 lenovo_keycode_map[] __initdata = {
982
983 KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP,
984 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
985 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
986
987 KEY_UNKNOWN,
988 KEY_UNKNOWN,
989 KEY_UNKNOWN,
990 KEY_RESERVED,
991
992 KEY_RESERVED,
993 KEY_RESERVED,
994 KEY_UNKNOWN,
995 KEY_ZOOM,
996 KEY_RESERVED,
997 KEY_RESERVED,
998 KEY_RESERVED,
999 KEY_VENDOR,
1000
1001 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
1002 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
1003 };
1004
1005#define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map)
1006#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map)
1007#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0])
1008
1009 int res, i;
1010 int status;
1011 int hkeyv;
1012
1013 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
1014
1015 BUG_ON(!tpacpi_inputdev);
1016
1017 IBM_ACPIHANDLE_INIT(hkey);
1018 mutex_init(&hotkey_mutex);
1019
1020
1021 tp_features.hotkey = hkey_handle != NULL;
1022
1023 vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n",
1024 str_supported(tp_features.hotkey));
1025
1026 if (tp_features.hotkey) {
1027 hotkey_dev_attributes = create_attr_set(8, NULL);
1028 if (!hotkey_dev_attributes)
1029 return -ENOMEM;
1030 res = add_many_to_attr_set(hotkey_dev_attributes,
1031 hotkey_attributes,
1032 ARRAY_SIZE(hotkey_attributes));
1033 if (res)
1034 return res;
1035
1036
1037
1038
1039 if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
1040 if ((hkeyv >> 8) != 1) {
1041 printk(IBM_ERR "unknown version of the "
1042 "HKEY interface: 0x%x\n", hkeyv);
1043 printk(IBM_ERR "please report this to %s\n",
1044 IBM_MAIL);
1045 } else {
1046
1047
1048
1049
1050 tp_features.hotkey_mask = 1;
1051 }
1052 }
1053
1054 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
1055 str_supported(tp_features.hotkey_mask));
1056
1057 if (tp_features.hotkey_mask) {
1058 if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
1059 "MHKA", "qd")) {
1060 printk(IBM_ERR
1061 "missing MHKA handler, "
1062 "please report this to %s\n",
1063 IBM_MAIL);
1064 hotkey_all_mask = 0x080cU;
1065 }
1066 }
1067
1068 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
1069 if (!res && tp_features.hotkey_mask) {
1070 res = add_many_to_attr_set(hotkey_dev_attributes,
1071 hotkey_mask_attributes,
1072 ARRAY_SIZE(hotkey_mask_attributes));
1073 }
1074
1075
1076 if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
1077 tp_features.hotkey_wlsw = 1;
1078 printk(IBM_INFO
1079 "radio switch found; radios are %s\n",
1080 enabled(status, 0));
1081 res = add_to_attr_set(hotkey_dev_attributes,
1082 &dev_attr_hotkey_radio_sw.attr);
1083 }
1084
1085 if (!res)
1086 res = register_attr_set_with_sysfs(
1087 hotkey_dev_attributes,
1088 &tpacpi_pdev->dev.kobj);
1089 if (res)
1090 return res;
1091
1092
1093
1094 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
1095 GFP_KERNEL);
1096 if (!hotkey_keycode_map) {
1097 printk(IBM_ERR "failed to allocate memory for key map\n");
1098 return -ENOMEM;
1099 }
1100
1101 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
1102 dbg_printk(TPACPI_DBG_INIT,
1103 "using Lenovo default hot key map\n");
1104 memcpy(hotkey_keycode_map, &lenovo_keycode_map,
1105 TPACPI_HOTKEY_MAP_SIZE);
1106 } else {
1107 dbg_printk(TPACPI_DBG_INIT,
1108 "using IBM default hot key map\n");
1109 memcpy(hotkey_keycode_map, &ibm_keycode_map,
1110 TPACPI_HOTKEY_MAP_SIZE);
1111 }
1112
1113 set_bit(EV_KEY, tpacpi_inputdev->evbit);
1114 set_bit(EV_MSC, tpacpi_inputdev->evbit);
1115 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
1116 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
1117 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
1118 tpacpi_inputdev->keycode = hotkey_keycode_map;
1119 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
1120 if (hotkey_keycode_map[i] != KEY_RESERVED) {
1121 set_bit(hotkey_keycode_map[i],
1122 tpacpi_inputdev->keybit);
1123 } else {
1124 if (i < sizeof(hotkey_reserved_mask)*8)
1125 hotkey_reserved_mask |= 1 << i;
1126 }
1127 }
1128
1129 if (tp_features.hotkey_wlsw) {
1130 set_bit(EV_SW, tpacpi_inputdev->evbit);
1131 set_bit(SW_RADIO, tpacpi_inputdev->swbit);
1132 }
1133
1134 dbg_printk(TPACPI_DBG_INIT,
1135 "enabling hot key handling\n");
1136 res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)
1137 | hotkey_orig_mask);
1138 if (res)
1139 return res;
1140
1141 dbg_printk(TPACPI_DBG_INIT,
1142 "legacy hot key reporting over procfs %s\n",
1143 (hotkey_report_mode < 2) ?
1144 "enabled" : "disabled");
1145 }
1146
1147 return (tp_features.hotkey)? 0 : 1;
1148}
1149
1150static void hotkey_exit(void)
1151{
1152 int res;
1153
1154 if (tp_features.hotkey) {
1155 dbg_printk(TPACPI_DBG_EXIT, "restoring original hotkey mask\n");
1156 res = hotkey_set(hotkey_orig_status, hotkey_orig_mask);
1157 if (res)
1158 printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n");
1159 }
1160
1161 if (hotkey_dev_attributes) {
1162 delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
1163 hotkey_dev_attributes = NULL;
1164 }
1165}
1166
1167static void tpacpi_input_send_key(unsigned int scancode,
1168 unsigned int keycode)
1169{
1170 if (keycode != KEY_RESERVED) {
1171 mutex_lock(&tpacpi_inputdev_send_mutex);
1172
1173 input_report_key(tpacpi_inputdev, keycode, 1);
1174 if (keycode == KEY_UNKNOWN)
1175 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1176 scancode);
1177 input_sync(tpacpi_inputdev);
1178
1179 input_report_key(tpacpi_inputdev, keycode, 0);
1180 if (keycode == KEY_UNKNOWN)
1181 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1182 scancode);
1183 input_sync(tpacpi_inputdev);
1184
1185 mutex_unlock(&tpacpi_inputdev_send_mutex);
1186 }
1187}
1188
1189static void tpacpi_input_send_radiosw(void)
1190{
1191 int wlsw;
1192
1193 mutex_lock(&tpacpi_inputdev_send_mutex);
1194
1195 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
1196 input_report_switch(tpacpi_inputdev,
1197 SW_RADIO, !!wlsw);
1198 input_sync(tpacpi_inputdev);
1199 }
1200
1201 mutex_unlock(&tpacpi_inputdev_send_mutex);
1202}
1203
1204static void hotkey_notify(struct ibm_struct *ibm, u32 event)
1205{
1206 u32 hkey;
1207 unsigned int keycode, scancode;
1208 int send_acpi_ev;
1209 int ignore_acpi_ev;
1210
1211 if (event != 0x80) {
1212 printk(IBM_ERR "unknown HKEY notification event %d\n", event);
1213
1214 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
1215 ibm->acpi->device->dev.bus_id,
1216 event, 0);
1217 return;
1218 }
1219
1220 while (1) {
1221 if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
1222 printk(IBM_ERR "failed to retrieve HKEY event\n");
1223 return;
1224 }
1225
1226 if (hkey == 0) {
1227
1228 return;
1229 }
1230
1231 send_acpi_ev = 0;
1232 ignore_acpi_ev = 0;
1233
1234 switch (hkey >> 12) {
1235 case 1:
1236
1237 scancode = hkey & 0xfff;
1238 if (scancode > 0 && scancode < 0x21) {
1239 scancode--;
1240 keycode = hotkey_keycode_map[scancode];
1241 tpacpi_input_send_key(scancode, keycode);
1242 } else {
1243 printk(IBM_ERR
1244 "hotkey 0x%04x out of range for keyboard map\n",
1245 hkey);
1246 send_acpi_ev = 1;
1247 }
1248 break;
1249 case 5:
1250
1251
1252
1253 if (hkey != 0x5001 && hkey != 0x5002) {
1254 printk(IBM_ERR
1255 "unknown LID-related HKEY event: 0x%04x\n",
1256 hkey);
1257 send_acpi_ev = 1;
1258 } else {
1259 ignore_acpi_ev = 1;
1260 }
1261 break;
1262 case 7:
1263
1264 if (tp_features.hotkey_wlsw && hkey == 0x7000) {
1265 tpacpi_input_send_radiosw();
1266 break;
1267 }
1268
1269 default:
1270
1271
1272
1273
1274 printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
1275 send_acpi_ev = 1;
1276 }
1277
1278
1279 if (!ignore_acpi_ev && (send_acpi_ev || hotkey_report_mode < 2)) {
1280 acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
1281 }
1282
1283
1284 if (!ignore_acpi_ev && send_acpi_ev) {
1285 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
1286 ibm->acpi->device->dev.bus_id,
1287 event, hkey);
1288 }
1289 }
1290}
1291
1292static void hotkey_resume(void)
1293{
1294 tpacpi_input_send_radiosw();
1295}
1296
1297
1298
1299
1300static int hotkey_get(int *status, u32 *mask)
1301{
1302 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
1303 return -EIO;
1304
1305 if (tp_features.hotkey_mask)
1306 if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
1307 return -EIO;
1308
1309 return 0;
1310}
1311
1312
1313
1314
1315static int hotkey_set(int status, u32 mask)
1316{
1317 int i;
1318
1319 if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
1320 return -EIO;
1321
1322 if (tp_features.hotkey_mask)
1323 for (i = 0; i < 32; i++) {
1324 int bit = ((1 << i) & mask) != 0;
1325 if (!acpi_evalf(hkey_handle,
1326 NULL, "MHKM", "vdd", i + 1, bit))
1327 return -EIO;
1328 }
1329
1330 return 0;
1331}
1332
1333
1334static int hotkey_read(char *p)
1335{
1336 int res, status;
1337 u32 mask;
1338 int len = 0;
1339
1340 if (!tp_features.hotkey) {
1341 len += sprintf(p + len, "status:\t\tnot supported\n");
1342 return len;
1343 }
1344
1345 if (mutex_lock_interruptible(&hotkey_mutex))
1346 return -ERESTARTSYS;
1347 res = hotkey_get(&status, &mask);
1348 mutex_unlock(&hotkey_mutex);
1349 if (res)
1350 return res;
1351
1352 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
1353 if (tp_features.hotkey_mask) {
1354 len += sprintf(p + len, "mask:\t\t0x%08x\n", mask);
1355 len += sprintf(p + len,
1356 "commands:\tenable, disable, reset, <mask>\n");
1357 } else {
1358 len += sprintf(p + len, "mask:\t\tnot supported\n");
1359 len += sprintf(p + len, "commands:\tenable, disable, reset\n");
1360 }
1361
1362 return len;
1363}
1364
1365static int hotkey_write(char *buf)
1366{
1367 int res, status;
1368 u32 mask;
1369 char *cmd;
1370 int do_cmd = 0;
1371
1372 if (!tp_features.hotkey)
1373 return -ENODEV;
1374
1375 if (mutex_lock_interruptible(&hotkey_mutex))
1376 return -ERESTARTSYS;
1377
1378 res = hotkey_get(&status, &mask);
1379 if (res)
1380 goto errexit;
1381
1382 res = 0;
1383 while ((cmd = next_cmd(&buf))) {
1384 if (strlencmp(cmd, "enable") == 0) {
1385 status = 1;
1386 } else if (strlencmp(cmd, "disable") == 0) {
1387 status = 0;
1388 } else if (strlencmp(cmd, "reset") == 0) {
1389 status = hotkey_orig_status;
1390 mask = hotkey_orig_mask;
1391 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
1392
1393 } else if (sscanf(cmd, "%x", &mask) == 1) {
1394
1395 } else {
1396 res = -EINVAL;
1397 goto errexit;
1398 }
1399 do_cmd = 1;
1400 }
1401
1402 if (do_cmd)
1403 res = hotkey_set(status, mask);
1404
1405errexit:
1406 mutex_unlock(&hotkey_mutex);
1407 return res;
1408}
1409
1410static const struct acpi_device_id ibm_htk_device_ids[] = {
1411 {IBM_HKEY_HID, 0},
1412 {"", 0},
1413};
1414
1415static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = {
1416 .hid = ibm_htk_device_ids,
1417 .notify = hotkey_notify,
1418 .handle = &hkey_handle,
1419 .type = ACPI_DEVICE_NOTIFY,
1420};
1421
1422static struct ibm_struct hotkey_driver_data = {
1423 .name = "hotkey",
1424 .read = hotkey_read,
1425 .write = hotkey_write,
1426 .exit = hotkey_exit,
1427 .resume = hotkey_resume,
1428 .acpi = &ibm_hotkey_acpidriver,
1429};
1430
1431
1432
1433
1434
1435
1436static ssize_t bluetooth_enable_show(struct device *dev,
1437 struct device_attribute *attr,
1438 char *buf)
1439{
1440 int status;
1441
1442 status = bluetooth_get_radiosw();
1443 if (status < 0)
1444 return status;
1445
1446 return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
1447}
1448
1449static ssize_t bluetooth_enable_store(struct device *dev,
1450 struct device_attribute *attr,
1451 const char *buf, size_t count)
1452{
1453 unsigned long t;
1454 int res;
1455
1456 if (parse_strtoul(buf, 1, &t))
1457 return -EINVAL;
1458
1459 res = bluetooth_set_radiosw(t);
1460
1461 return (res) ? res : count;
1462}
1463
1464static struct device_attribute dev_attr_bluetooth_enable =
1465 __ATTR(bluetooth_enable, S_IWUSR | S_IRUGO,
1466 bluetooth_enable_show, bluetooth_enable_store);
1467
1468
1469
1470static struct attribute *bluetooth_attributes[] = {
1471 &dev_attr_bluetooth_enable.attr,
1472 NULL
1473};
1474
1475static const struct attribute_group bluetooth_attr_group = {
1476 .attrs = bluetooth_attributes,
1477};
1478
1479static int __init bluetooth_init(struct ibm_init_struct *iibm)
1480{
1481 int res;
1482 int status = 0;
1483
1484 vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n");
1485
1486 IBM_ACPIHANDLE_INIT(hkey);
1487
1488
1489
1490 tp_features.bluetooth = hkey_handle &&
1491 acpi_evalf(hkey_handle, &status, "GBDC", "qd");
1492
1493 vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s, status 0x%02x\n",
1494 str_supported(tp_features.bluetooth),
1495 status);
1496
1497 if (tp_features.bluetooth) {
1498 if (!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
1499
1500 tp_features.bluetooth = 0;
1501 dbg_printk(TPACPI_DBG_INIT,
1502 "bluetooth hardware not installed\n");
1503 } else {
1504 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
1505 &bluetooth_attr_group);
1506 if (res)
1507 return res;
1508 }
1509 }
1510
1511 return (tp_features.bluetooth)? 0 : 1;
1512}
1513
1514static void bluetooth_exit(void)
1515{
1516 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
1517 &bluetooth_attr_group);
1518}
1519
1520static int bluetooth_get_radiosw(void)
1521{
1522 int status;
1523
1524 if (!tp_features.bluetooth)
1525 return -ENODEV;
1526
1527 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
1528 return -EIO;
1529
1530 return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0);
1531}
1532
1533static int bluetooth_set_radiosw(int radio_on)
1534{
1535 int status;
1536
1537 if (!tp_features.bluetooth)
1538 return -ENODEV;
1539
1540 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
1541 return -EIO;
1542 if (radio_on)
1543 status |= TP_ACPI_BLUETOOTH_RADIOSSW;
1544 else
1545 status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
1546 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
1547 return -EIO;
1548
1549 return 0;
1550}
1551
1552
1553static int bluetooth_read(char *p)
1554{
1555 int len = 0;
1556 int status = bluetooth_get_radiosw();
1557
1558 if (!tp_features.bluetooth)
1559 len += sprintf(p + len, "status:\t\tnot supported\n");
1560 else {
1561 len += sprintf(p + len, "status:\t\t%s\n",
1562 (status)? "enabled" : "disabled");
1563 len += sprintf(p + len, "commands:\tenable, disable\n");
1564 }
1565
1566 return len;
1567}
1568
1569static int bluetooth_write(char *buf)
1570{
1571 char *cmd;
1572
1573 if (!tp_features.bluetooth)
1574 return -ENODEV;
1575
1576 while ((cmd = next_cmd(&buf))) {
1577 if (strlencmp(cmd, "enable") == 0) {
1578 bluetooth_set_radiosw(1);
1579 } else if (strlencmp(cmd, "disable") == 0) {
1580 bluetooth_set_radiosw(0);
1581 } else
1582 return -EINVAL;
1583 }
1584
1585 return 0;
1586}
1587
1588static struct ibm_struct bluetooth_driver_data = {
1589 .name = "bluetooth",
1590 .read = bluetooth_read,
1591 .write = bluetooth_write,
1592 .exit = bluetooth_exit,
1593};
1594
1595
1596
1597
1598
1599
1600static ssize_t wan_enable_show(struct device *dev,
1601 struct device_attribute *attr,
1602 char *buf)
1603{
1604 int status;
1605
1606 status = wan_get_radiosw();
1607 if (status < 0)
1608 return status;
1609
1610 return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
1611}
1612
1613static ssize_t wan_enable_store(struct device *dev,
1614 struct device_attribute *attr,
1615 const char *buf, size_t count)
1616{
1617 unsigned long t;
1618 int res;
1619
1620 if (parse_strtoul(buf, 1, &t))
1621 return -EINVAL;
1622
1623 res = wan_set_radiosw(t);
1624
1625 return (res) ? res : count;
1626}
1627
1628static struct device_attribute dev_attr_wan_enable =
1629 __ATTR(wwan_enable, S_IWUSR | S_IRUGO,
1630 wan_enable_show, wan_enable_store);
1631
1632
1633
1634static struct attribute *wan_attributes[] = {
1635 &dev_attr_wan_enable.attr,
1636 NULL
1637};
1638
1639static const struct attribute_group wan_attr_group = {
1640 .attrs = wan_attributes,
1641};
1642
1643static int __init wan_init(struct ibm_init_struct *iibm)
1644{
1645 int res;
1646 int status = 0;
1647
1648 vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n");
1649
1650 IBM_ACPIHANDLE_INIT(hkey);
1651
1652 tp_features.wan = hkey_handle &&
1653 acpi_evalf(hkey_handle, &status, "GWAN", "qd");
1654
1655 vdbg_printk(TPACPI_DBG_INIT, "wan is %s, status 0x%02x\n",
1656 str_supported(tp_features.wan),
1657 status);
1658
1659 if (tp_features.wan) {
1660 if (!(status & TP_ACPI_WANCARD_HWPRESENT)) {
1661
1662 tp_features.wan = 0;
1663 dbg_printk(TPACPI_DBG_INIT,
1664 "wan hardware not installed\n");
1665 } else {
1666 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
1667 &wan_attr_group);
1668 if (res)
1669 return res;
1670 }
1671 }
1672
1673 return (tp_features.wan)? 0 : 1;
1674}
1675
1676static void wan_exit(void)
1677{
1678 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
1679 &wan_attr_group);
1680}
1681
1682static int wan_get_radiosw(void)
1683{
1684 int status;
1685
1686 if (!tp_features.wan)
1687 return -ENODEV;
1688
1689 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
1690 return -EIO;
1691
1692 return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0);
1693}
1694
1695static int wan_set_radiosw(int radio_on)
1696{
1697 int status;
1698
1699 if (!tp_features.wan)
1700 return -ENODEV;
1701
1702 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
1703 return -EIO;
1704 if (radio_on)
1705 status |= TP_ACPI_WANCARD_RADIOSSW;
1706 else
1707 status &= ~TP_ACPI_WANCARD_RADIOSSW;
1708 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
1709 return -EIO;
1710
1711 return 0;
1712}
1713
1714
1715static int wan_read(char *p)
1716{
1717 int len = 0;
1718 int status = wan_get_radiosw();
1719
1720 if (!tp_features.wan)
1721 len += sprintf(p + len, "status:\t\tnot supported\n");
1722 else {
1723 len += sprintf(p + len, "status:\t\t%s\n",
1724 (status)? "enabled" : "disabled");
1725 len += sprintf(p + len, "commands:\tenable, disable\n");
1726 }
1727
1728 return len;
1729}
1730
1731static int wan_write(char *buf)
1732{
1733 char *cmd;
1734
1735 if (!tp_features.wan)
1736 return -ENODEV;
1737
1738 while ((cmd = next_cmd(&buf))) {
1739 if (strlencmp(cmd, "enable") == 0) {
1740 wan_set_radiosw(1);
1741 } else if (strlencmp(cmd, "disable") == 0) {
1742 wan_set_radiosw(0);
1743 } else
1744 return -EINVAL;
1745 }
1746
1747 return 0;
1748}
1749
1750static struct ibm_struct wan_driver_data = {
1751 .name = "wan",
1752 .read = wan_read,
1753 .write = wan_write,
1754 .exit = wan_exit,
1755 .flags.experimental = 1,
1756};
1757
1758
1759
1760
1761
1762static enum video_access_mode video_supported;
1763static int video_orig_autosw;
1764
1765IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA",
1766 "\\_SB.PCI0.AGP0.VID0",
1767 "\\_SB.PCI0.VID0",
1768 "\\_SB.PCI0.VID",
1769 "\\_SB.PCI0.AGP.VID",
1770 );
1771
1772IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID");
1773
1774static int __init video_init(struct ibm_init_struct *iibm)
1775{
1776 int ivga;
1777
1778 vdbg_printk(TPACPI_DBG_INIT, "initializing video subdriver\n");
1779
1780 IBM_ACPIHANDLE_INIT(vid);
1781 IBM_ACPIHANDLE_INIT(vid2);
1782
1783 if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
1784
1785 vid_handle = vid2_handle;
1786
1787 if (!vid_handle)
1788
1789 video_supported = TPACPI_VIDEO_NONE;
1790 else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
1791
1792 video_supported = TPACPI_VIDEO_570;
1793 else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
1794
1795 video_supported = TPACPI_VIDEO_770;
1796 else
1797
1798 video_supported = TPACPI_VIDEO_NEW;
1799
1800 vdbg_printk(TPACPI_DBG_INIT, "video is %s, mode %d\n",
1801 str_supported(video_supported != TPACPI_VIDEO_NONE),
1802 video_supported);
1803
1804 return (video_supported != TPACPI_VIDEO_NONE)? 0 : 1;
1805}
1806
1807static void video_exit(void)
1808{
1809 dbg_printk(TPACPI_DBG_EXIT,
1810 "restoring original video autoswitch mode\n");
1811 if (video_autosw_set(video_orig_autosw))
1812 printk(IBM_ERR "error while trying to restore original "
1813 "video autoswitch mode\n");
1814}
1815
1816static int video_outputsw_get(void)
1817{
1818 int status = 0;
1819 int i;
1820
1821 switch (video_supported) {
1822 case TPACPI_VIDEO_570:
1823 if (!acpi_evalf(NULL, &i, "\\_SB.PHS", "dd",
1824 TP_ACPI_VIDEO_570_PHSCMD))
1825 return -EIO;
1826 status = i & TP_ACPI_VIDEO_570_PHSMASK;
1827 break;
1828 case TPACPI_VIDEO_770:
1829 if (!acpi_evalf(NULL, &i, "\\VCDL", "d"))
1830 return -EIO;
1831 if (i)
1832 status |= TP_ACPI_VIDEO_S_LCD;
1833 if (!acpi_evalf(NULL, &i, "\\VCDC", "d"))
1834 return -EIO;
1835 if (i)
1836 status |= TP_ACPI_VIDEO_S_CRT;
1837 break;
1838 case TPACPI_VIDEO_NEW:
1839 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1) ||
1840 !acpi_evalf(NULL, &i, "\\VCDC", "d"))
1841 return -EIO;
1842 if (i)
1843 status |= TP_ACPI_VIDEO_S_CRT;
1844
1845 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0) ||
1846 !acpi_evalf(NULL, &i, "\\VCDL", "d"))
1847 return -EIO;
1848 if (i)
1849 status |= TP_ACPI_VIDEO_S_LCD;
1850 if (!acpi_evalf(NULL, &i, "\\VCDD", "d"))
1851 return -EIO;
1852 if (i)
1853 status |= TP_ACPI_VIDEO_S_DVI;
1854 break;
1855 default:
1856 return -ENOSYS;
1857 }
1858
1859 return status;
1860}
1861
1862static int video_outputsw_set(int status)
1863{
1864 int autosw;
1865 int res = 0;
1866
1867 switch (video_supported) {
1868 case TPACPI_VIDEO_570:
1869 res = acpi_evalf(NULL, NULL,
1870 "\\_SB.PHS2", "vdd",
1871 TP_ACPI_VIDEO_570_PHS2CMD,
1872 status | TP_ACPI_VIDEO_570_PHS2SET);
1873 break;
1874 case TPACPI_VIDEO_770:
1875 autosw = video_autosw_get();
1876 if (autosw < 0)
1877 return autosw;
1878
1879 res = video_autosw_set(1);
1880 if (res)
1881 return res;
1882 res = acpi_evalf(vid_handle, NULL,
1883 "ASWT", "vdd", status * 0x100, 0);
1884 if (!autosw && video_autosw_set(autosw)) {
1885 printk(IBM_ERR "video auto-switch left enabled due to error\n");
1886 return -EIO;
1887 }
1888 break;
1889 case TPACPI_VIDEO_NEW:
1890 res = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
1891 acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
1892 break;
1893 default:
1894 return -ENOSYS;
1895 }
1896
1897 return (res)? 0 : -EIO;
1898}
1899
1900static int video_autosw_get(void)
1901{
1902 int autosw = 0;
1903
1904 switch (video_supported) {
1905 case TPACPI_VIDEO_570:
1906 if (!acpi_evalf(vid_handle, &autosw, "SWIT", "d"))
1907 return -EIO;
1908 break;
1909 case TPACPI_VIDEO_770:
1910 case TPACPI_VIDEO_NEW:
1911 if (!acpi_evalf(vid_handle, &autosw, "^VDEE", "d"))
1912 return -EIO;
1913 break;
1914 default:
1915 return -ENOSYS;
1916 }
1917
1918 return autosw & 1;
1919}
1920
1921static int video_autosw_set(int enable)
1922{
1923 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable)? 1 : 0))
1924 return -EIO;
1925 return 0;
1926}
1927
1928static int video_outputsw_cycle(void)
1929{
1930 int autosw = video_autosw_get();
1931 int res;
1932
1933 if (autosw < 0)
1934 return autosw;
1935
1936 switch (video_supported) {
1937 case TPACPI_VIDEO_570:
1938 res = video_autosw_set(1);
1939 if (res)
1940 return res;
1941 res = acpi_evalf(ec_handle, NULL, "_Q16", "v");
1942 break;
1943 case TPACPI_VIDEO_770:
1944 case TPACPI_VIDEO_NEW:
1945 res = video_autosw_set(1);
1946 if (res)
1947 return res;
1948 res = acpi_evalf(vid_handle, NULL, "VSWT", "v");
1949 break;
1950 default:
1951 return -ENOSYS;
1952 }
1953 if (!autosw && video_autosw_set(autosw)) {
1954 printk(IBM_ERR "video auto-switch left enabled due to error\n");
1955 return -EIO;
1956 }
1957
1958 return (res)? 0 : -EIO;
1959}
1960
1961static int video_expand_toggle(void)
1962{
1963 switch (video_supported) {
1964 case TPACPI_VIDEO_570:
1965 return acpi_evalf(ec_handle, NULL, "_Q17", "v")?
1966 0 : -EIO;
1967 case TPACPI_VIDEO_770:
1968 return acpi_evalf(vid_handle, NULL, "VEXP", "v")?
1969 0 : -EIO;
1970 case TPACPI_VIDEO_NEW:
1971 return acpi_evalf(NULL, NULL, "\\VEXP", "v")?
1972 0 : -EIO;
1973 default:
1974 return -ENOSYS;
1975 }
1976
1977}
1978
1979static int video_read(char *p)
1980{
1981 int status, autosw;
1982 int len = 0;
1983
1984 if (video_supported == TPACPI_VIDEO_NONE) {
1985 len += sprintf(p + len, "status:\t\tnot supported\n");
1986 return len;
1987 }
1988
1989 status = video_outputsw_get();
1990 if (status < 0)
1991 return status;
1992
1993 autosw = video_autosw_get();
1994 if (autosw < 0)
1995 return autosw;
1996
1997 len += sprintf(p + len, "status:\t\tsupported\n");
1998 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
1999 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
2000 if (video_supported == TPACPI_VIDEO_NEW)
2001 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
2002 len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
2003 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
2004 len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
2005 if (video_supported == TPACPI_VIDEO_NEW)
2006 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
2007 len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
2008 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
2009
2010 return len;
2011}
2012
2013static int video_write(char *buf)
2014{
2015 char *cmd;
2016 int enable, disable, status;
2017 int res;
2018
2019 if (video_supported == TPACPI_VIDEO_NONE)
2020 return -ENODEV;
2021
2022 enable = 0;
2023 disable = 0;
2024
2025 while ((cmd = next_cmd(&buf))) {
2026 if (strlencmp(cmd, "lcd_enable") == 0) {
2027 enable |= TP_ACPI_VIDEO_S_LCD;
2028 } else if (strlencmp(cmd, "lcd_disable") == 0) {
2029 disable |= TP_ACPI_VIDEO_S_LCD;
2030 } else if (strlencmp(cmd, "crt_enable") == 0) {
2031 enable |= TP_ACPI_VIDEO_S_CRT;
2032 } else if (strlencmp(cmd, "crt_disable") == 0) {
2033 disable |= TP_ACPI_VIDEO_S_CRT;
2034 } else if (video_supported == TPACPI_VIDEO_NEW &&
2035 strlencmp(cmd, "dvi_enable") == 0) {
2036 enable |= TP_ACPI_VIDEO_S_DVI;
2037 } else if (video_supported == TPACPI_VIDEO_NEW &&
2038 strlencmp(cmd, "dvi_disable") == 0) {
2039 disable |= TP_ACPI_VIDEO_S_DVI;
2040 } else if (strlencmp(cmd, "auto_enable") == 0) {
2041 res = video_autosw_set(1);
2042 if (res)
2043 return res;
2044 } else if (strlencmp(cmd, "auto_disable") == 0) {
2045 res = video_autosw_set(0);
2046 if (res)
2047 return res;
2048 } else if (strlencmp(cmd, "video_switch") == 0) {
2049 res = video_outputsw_cycle();
2050 if (res)
2051 return res;
2052 } else if (strlencmp(cmd, "expand_toggle") == 0) {
2053 res = video_expand_toggle();
2054 if (res)
2055 return res;
2056 } else
2057 return -EINVAL;
2058 }
2059
2060 if (enable || disable) {
2061 status = video_outputsw_get();
2062 if (status < 0)
2063 return status;
2064 res = video_outputsw_set((status & ~disable) | enable);
2065 if (res)
2066 return res;
2067 }
2068
2069 return 0;
2070}
2071
2072static struct ibm_struct video_driver_data = {
2073 .name = "video",
2074 .read = video_read,
2075 .write = video_write,
2076 .exit = video_exit,
2077};
2078
2079
2080
2081
2082
2083IBM_HANDLE(lght, root, "\\LGHT");
2084IBM_HANDLE(ledb, ec, "LEDB");
2085
2086static int __init light_init(struct ibm_init_struct *iibm)
2087{
2088 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
2089
2090 IBM_ACPIHANDLE_INIT(ledb);
2091 IBM_ACPIHANDLE_INIT(lght);
2092 IBM_ACPIHANDLE_INIT(cmos);
2093
2094
2095 tp_features.light = (cmos_handle || lght_handle) && !ledb_handle;
2096
2097 if (tp_features.light)
2098
2099
2100 tp_features.light_status =
2101 acpi_evalf(ec_handle, NULL, "KBLT", "qv");
2102
2103 vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
2104 str_supported(tp_features.light));
2105
2106 return (tp_features.light)? 0 : 1;
2107}
2108
2109static int light_read(char *p)
2110{
2111 int len = 0;
2112 int status = 0;
2113
2114 if (!tp_features.light) {
2115 len += sprintf(p + len, "status:\t\tnot supported\n");
2116 } else if (!tp_features.light_status) {
2117 len += sprintf(p + len, "status:\t\tunknown\n");
2118 len += sprintf(p + len, "commands:\ton, off\n");
2119 } else {
2120 if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
2121 return -EIO;
2122 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
2123 len += sprintf(p + len, "commands:\ton, off\n");
2124 }
2125
2126 return len;
2127}
2128
2129static int light_write(char *buf)
2130{
2131 int cmos_cmd, lght_cmd;
2132 char *cmd;
2133 int success;
2134
2135 if (!tp_features.light)
2136 return -ENODEV;
2137
2138 while ((cmd = next_cmd(&buf))) {
2139 if (strlencmp(cmd, "on") == 0) {
2140 cmos_cmd = 0x0c;
2141 lght_cmd = 1;
2142 } else if (strlencmp(cmd, "off") == 0) {
2143 cmos_cmd = 0x0d;
2144 lght_cmd = 0;
2145 } else
2146 return -EINVAL;
2147
2148 success = cmos_handle ?
2149 acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
2150 acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
2151 if (!success)
2152 return -EIO;
2153 }
2154
2155 return 0;
2156}
2157
2158static struct ibm_struct light_driver_data = {
2159 .name = "light",
2160 .read = light_read,
2161 .write = light_write,
2162};
2163
2164
2165
2166
2167
2168#ifdef CONFIG_THINKPAD_ACPI_DOCK
2169
2170IBM_HANDLE(dock, root, "\\_SB.GDCK",
2171 "\\_SB.PCI0.DOCK",
2172 "\\_SB.PCI0.PCI1.DOCK",
2173 "\\_SB.PCI.ISA.SLCE",
2174 );
2175
2176
2177IBM_HANDLE(pci, root, "\\_SB.PCI");
2178
2179static const struct acpi_device_id ibm_pci_device_ids[] = {
2180 {PCI_ROOT_HID_STRING, 0},
2181 {"", 0},
2182};
2183
2184static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = {
2185 {
2186 .notify = dock_notify,
2187 .handle = &dock_handle,
2188 .type = ACPI_SYSTEM_NOTIFY,
2189 },
2190 {
2191
2192
2193
2194 .hid = ibm_pci_device_ids,
2195 .notify = dock_notify,
2196 .handle = &pci_handle,
2197 .type = ACPI_SYSTEM_NOTIFY,
2198 },
2199};
2200
2201static struct ibm_struct dock_driver_data[2] = {
2202 {
2203 .name = "dock",
2204 .read = dock_read,
2205 .write = dock_write,
2206 .acpi = &ibm_dock_acpidriver[0],
2207 },
2208 {
2209 .name = "dock",
2210 .acpi = &ibm_dock_acpidriver[1],
2211 },
2212};
2213
2214#define dock_docked() (_sta(dock_handle) & 1)
2215
2216static int __init dock_init(struct ibm_init_struct *iibm)
2217{
2218 vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n");
2219
2220 IBM_ACPIHANDLE_INIT(dock);
2221
2222 vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n",
2223 str_supported(dock_handle != NULL));
2224
2225 return (dock_handle)? 0 : 1;
2226}
2227
2228static int __init dock_init2(struct ibm_init_struct *iibm)
2229{
2230 int dock2_needed;
2231
2232 vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver part 2\n");
2233
2234 if (dock_driver_data[0].flags.acpi_driver_registered &&
2235 dock_driver_data[0].flags.acpi_notify_installed) {
2236 IBM_ACPIHANDLE_INIT(pci);
2237 dock2_needed = (pci_handle != NULL);
2238 vdbg_printk(TPACPI_DBG_INIT,
2239 "dock PCI handler for the TP 570 is %s\n",
2240 str_supported(dock2_needed));
2241 } else {
2242 vdbg_printk(TPACPI_DBG_INIT,
2243 "dock subdriver part 2 not required\n");
2244 dock2_needed = 0;
2245 }
2246
2247 return (dock2_needed)? 0 : 1;
2248}
2249
2250static void dock_notify(struct ibm_struct *ibm, u32 event)
2251{
2252 int docked = dock_docked();
2253 int pci = ibm->acpi->hid && ibm->acpi->device &&
2254 acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids);
2255 int data;
2256
2257 if (event == 1 && !pci)
2258 data = 1;
2259 else if (event == 1 && pci)
2260 data = 3;
2261 else if (event == 3 && docked)
2262 data = 1;
2263 else if (event == 3 && !docked)
2264 data = 2;
2265 else if (event == 0 && docked)
2266 data = 3;
2267 else {
2268 printk(IBM_ERR "unknown dock event %d, status %d\n",
2269 event, _sta(dock_handle));
2270 data = 0;
2271 }
2272 acpi_bus_generate_proc_event(ibm->acpi->device, event, data);
2273 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
2274 ibm->acpi->device->dev.bus_id,
2275 event, data);
2276}
2277
2278static int dock_read(char *p)
2279{
2280 int len = 0;
2281 int docked = dock_docked();
2282
2283 if (!dock_handle)
2284 len += sprintf(p + len, "status:\t\tnot supported\n");
2285 else if (!docked)
2286 len += sprintf(p + len, "status:\t\tundocked\n");
2287 else {
2288 len += sprintf(p + len, "status:\t\tdocked\n");
2289 len += sprintf(p + len, "commands:\tdock, undock\n");
2290 }
2291
2292 return len;
2293}
2294
2295static int dock_write(char *buf)
2296{
2297 char *cmd;
2298
2299 if (!dock_docked())
2300 return -ENODEV;
2301
2302 while ((cmd = next_cmd(&buf))) {
2303 if (strlencmp(cmd, "undock") == 0) {
2304 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
2305 !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
2306 return -EIO;
2307 } else if (strlencmp(cmd, "dock") == 0) {
2308 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
2309 return -EIO;
2310 } else
2311 return -EINVAL;
2312 }
2313
2314 return 0;
2315}
2316
2317#endif
2318
2319
2320
2321
2322
2323#ifdef CONFIG_THINKPAD_ACPI_BAY
2324IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",
2325 "\\_SB.PCI0.IDE0.IDES.IDSM",
2326 "\\_SB.PCI0.SATA.SCND.MSTR",
2327 "\\_SB.PCI0.IDE0.SCND.MSTR",
2328 );
2329IBM_HANDLE(bay_ej, bay, "_EJ3",
2330 "_EJ0",
2331 );
2332IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV",
2333 "\\_SB.PCI0.IDE0.IDEP.IDPS",
2334 );
2335IBM_HANDLE(bay2_ej, bay2, "_EJ3",
2336 "_EJ0",
2337 );
2338
2339static int __init bay_init(struct ibm_init_struct *iibm)
2340{
2341 vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n");
2342
2343 IBM_ACPIHANDLE_INIT(bay);
2344 if (bay_handle)
2345 IBM_ACPIHANDLE_INIT(bay_ej);
2346 IBM_ACPIHANDLE_INIT(bay2);
2347 if (bay2_handle)
2348 IBM_ACPIHANDLE_INIT(bay2_ej);
2349
2350 tp_features.bay_status = bay_handle &&
2351 acpi_evalf(bay_handle, NULL, "_STA", "qv");
2352 tp_features.bay_status2 = bay2_handle &&
2353 acpi_evalf(bay2_handle, NULL, "_STA", "qv");
2354
2355 tp_features.bay_eject = bay_handle && bay_ej_handle &&
2356 (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
2357 tp_features.bay_eject2 = bay2_handle && bay2_ej_handle &&
2358 (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
2359
2360 vdbg_printk(TPACPI_DBG_INIT,
2361 "bay 1: status %s, eject %s; bay 2: status %s, eject %s\n",
2362 str_supported(tp_features.bay_status),
2363 str_supported(tp_features.bay_eject),
2364 str_supported(tp_features.bay_status2),
2365 str_supported(tp_features.bay_eject2));
2366
2367 return (tp_features.bay_status || tp_features.bay_eject ||
2368 tp_features.bay_status2 || tp_features.bay_eject2)? 0 : 1;
2369}
2370
2371static void bay_notify(struct ibm_struct *ibm, u32 event)
2372{
2373 acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
2374 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
2375 ibm->acpi->device->dev.bus_id,
2376 event, 0);
2377}
2378
2379#define bay_occupied(b) (_sta(b##_handle) & 1)
2380
2381static int bay_read(char *p)
2382{
2383 int len = 0;
2384 int occupied = bay_occupied(bay);
2385 int occupied2 = bay_occupied(bay2);
2386 int eject, eject2;
2387
2388 len += sprintf(p + len, "status:\t\t%s\n",
2389 tp_features.bay_status ?
2390 (occupied ? "occupied" : "unoccupied") :
2391 "not supported");
2392 if (tp_features.bay_status2)
2393 len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
2394 "occupied" : "unoccupied");
2395
2396 eject = tp_features.bay_eject && occupied;
2397 eject2 = tp_features.bay_eject2 && occupied2;
2398
2399 if (eject && eject2)
2400 len += sprintf(p + len, "commands:\teject, eject2\n");
2401 else if (eject)
2402 len += sprintf(p + len, "commands:\teject\n");
2403 else if (eject2)
2404 len += sprintf(p + len, "commands:\teject2\n");
2405
2406 return len;
2407}
2408
2409static int bay_write(char *buf)
2410{
2411 char *cmd;
2412
2413 if (!tp_features.bay_eject && !tp_features.bay_eject2)
2414 return -ENODEV;
2415
2416 while ((cmd = next_cmd(&buf))) {
2417 if (tp_features.bay_eject && strlencmp(cmd, "eject") == 0) {
2418 if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
2419 return -EIO;
2420 } else if (tp_features.bay_eject2 &&
2421 strlencmp(cmd, "eject2") == 0) {
2422 if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
2423 return -EIO;
2424 } else
2425 return -EINVAL;
2426 }
2427
2428 return 0;
2429}
2430
2431static struct tp_acpi_drv_struct ibm_bay_acpidriver = {
2432 .notify = bay_notify,
2433 .handle = &bay_handle,
2434 .type = ACPI_SYSTEM_NOTIFY,
2435};
2436
2437static struct ibm_struct bay_driver_data = {
2438 .name = "bay",
2439 .read = bay_read,
2440 .write = bay_write,
2441 .acpi = &ibm_bay_acpidriver,
2442};
2443
2444#endif
2445
2446
2447
2448
2449
2450
2451static ssize_t cmos_command_store(struct device *dev,
2452 struct device_attribute *attr,
2453 const char *buf, size_t count)
2454{
2455 unsigned long cmos_cmd;
2456 int res;
2457
2458 if (parse_strtoul(buf, 21, &cmos_cmd))
2459 return -EINVAL;
2460
2461 res = issue_thinkpad_cmos_command(cmos_cmd);
2462 return (res)? res : count;
2463}
2464
2465static struct device_attribute dev_attr_cmos_command =
2466 __ATTR(cmos_command, S_IWUSR, NULL, cmos_command_store);
2467
2468
2469
2470static int __init cmos_init(struct ibm_init_struct *iibm)
2471{
2472 int res;
2473
2474 vdbg_printk(TPACPI_DBG_INIT,
2475 "initializing cmos commands subdriver\n");
2476
2477 IBM_ACPIHANDLE_INIT(cmos);
2478
2479 vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n",
2480 str_supported(cmos_handle != NULL));
2481
2482 res = device_create_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
2483 if (res)
2484 return res;
2485
2486 return (cmos_handle)? 0 : 1;
2487}
2488
2489static void cmos_exit(void)
2490{
2491 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
2492}
2493
2494static int cmos_read(char *p)
2495{
2496 int len = 0;
2497
2498
2499
2500 if (!cmos_handle)
2501 len += sprintf(p + len, "status:\t\tnot supported\n");
2502 else {
2503 len += sprintf(p + len, "status:\t\tsupported\n");
2504 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
2505 }
2506
2507 return len;
2508}
2509
2510static int cmos_write(char *buf)
2511{
2512 char *cmd;
2513 int cmos_cmd, res;
2514
2515 while ((cmd = next_cmd(&buf))) {
2516 if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
2517 cmos_cmd >= 0 && cmos_cmd <= 21) {
2518
2519 } else
2520 return -EINVAL;
2521
2522 res = issue_thinkpad_cmos_command(cmos_cmd);
2523 if (res)
2524 return res;
2525 }
2526
2527 return 0;
2528}
2529
2530static struct ibm_struct cmos_driver_data = {
2531 .name = "cmos",
2532 .read = cmos_read,
2533 .write = cmos_write,
2534 .exit = cmos_exit,
2535};
2536
2537
2538
2539
2540
2541static enum led_access_mode led_supported;
2542
2543IBM_HANDLE(led, ec, "SLED",
2544 "SYSL",
2545 "LED",
2546 );
2547
2548static int __init led_init(struct ibm_init_struct *iibm)
2549{
2550 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
2551
2552 IBM_ACPIHANDLE_INIT(led);
2553
2554 if (!led_handle)
2555
2556 led_supported = TPACPI_LED_NONE;
2557 else if (strlencmp(led_path, "SLED") == 0)
2558
2559 led_supported = TPACPI_LED_570;
2560 else if (strlencmp(led_path, "SYSL") == 0)
2561
2562 led_supported = TPACPI_LED_OLD;
2563 else
2564
2565 led_supported = TPACPI_LED_NEW;
2566
2567 vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n",
2568 str_supported(led_supported), led_supported);
2569
2570 return (led_supported != TPACPI_LED_NONE)? 0 : 1;
2571}
2572
2573#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
2574
2575static int led_read(char *p)
2576{
2577 int len = 0;
2578
2579 if (!led_supported) {
2580 len += sprintf(p + len, "status:\t\tnot supported\n");
2581 return len;
2582 }
2583 len += sprintf(p + len, "status:\t\tsupported\n");
2584
2585 if (led_supported == TPACPI_LED_570) {
2586
2587 int i, status;
2588 for (i = 0; i < 8; i++) {
2589 if (!acpi_evalf(ec_handle,
2590 &status, "GLED", "dd", 1 << i))
2591 return -EIO;
2592 len += sprintf(p + len, "%d:\t\t%s\n",
2593 i, led_status(status));
2594 }
2595 }
2596
2597 len += sprintf(p + len, "commands:\t"
2598 "<led> on, <led> off, <led> blink (<led> is 0-7)\n");
2599
2600 return len;
2601}
2602
2603
2604static const int led_sled_arg1[] = { 0, 1, 3 };
2605static const int led_exp_hlbl[] = { 0, 0, 1 };
2606static const int led_exp_hlcl[] = { 0, 1, 1 };
2607static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
2608
2609static int led_write(char *buf)
2610{
2611 char *cmd;
2612 int led, ind, ret;
2613
2614 if (!led_supported)
2615 return -ENODEV;
2616
2617 while ((cmd = next_cmd(&buf))) {
2618 if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7)
2619 return -EINVAL;
2620
2621 if (strstr(cmd, "off")) {
2622 ind = 0;
2623 } else if (strstr(cmd, "on")) {
2624 ind = 1;
2625 } else if (strstr(cmd, "blink")) {
2626 ind = 2;
2627 } else
2628 return -EINVAL;
2629
2630 if (led_supported == TPACPI_LED_570) {
2631
2632 led = 1 << led;
2633 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
2634 led, led_sled_arg1[ind]))
2635 return -EIO;
2636 } else if (led_supported == TPACPI_LED_OLD) {
2637
2638 led = 1 << led;
2639 ret = ec_write(TPACPI_LED_EC_HLMS, led);
2640 if (ret >= 0)
2641 ret =
2642 ec_write(TPACPI_LED_EC_HLBL,
2643 led * led_exp_hlbl[ind]);
2644 if (ret >= 0)
2645 ret =
2646 ec_write(TPACPI_LED_EC_HLCL,
2647 led * led_exp_hlcl[ind]);
2648 if (ret < 0)
2649 return ret;
2650 } else {
2651
2652 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
2653 led, led_led_arg1[ind]))
2654 return -EIO;
2655 }
2656 }
2657
2658 return 0;
2659}
2660
2661static struct ibm_struct led_driver_data = {
2662 .name = "led",
2663 .read = led_read,
2664 .write = led_write,
2665};
2666
2667
2668
2669
2670
2671IBM_HANDLE(beep, ec, "BEEP");
2672
2673static int __init beep_init(struct ibm_init_struct *iibm)
2674{
2675 vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n");
2676
2677 IBM_ACPIHANDLE_INIT(beep);
2678
2679 vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n",
2680 str_supported(beep_handle != NULL));
2681
2682 return (beep_handle)? 0 : 1;
2683}
2684
2685static int beep_read(char *p)
2686{
2687 int len = 0;
2688
2689 if (!beep_handle)
2690 len += sprintf(p + len, "status:\t\tnot supported\n");
2691 else {
2692 len += sprintf(p + len, "status:\t\tsupported\n");
2693 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
2694 }
2695
2696 return len;
2697}
2698
2699static int beep_write(char *buf)
2700{
2701 char *cmd;
2702 int beep_cmd;
2703
2704 if (!beep_handle)
2705 return -ENODEV;
2706
2707 while ((cmd = next_cmd(&buf))) {
2708 if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
2709 beep_cmd >= 0 && beep_cmd <= 17) {
2710
2711 } else
2712 return -EINVAL;
2713 if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0))
2714 return -EIO;
2715 }
2716
2717 return 0;
2718}
2719
2720static struct ibm_struct beep_driver_data = {
2721 .name = "beep",
2722 .read = beep_read,
2723 .write = beep_write,
2724};
2725
2726
2727
2728
2729
2730static enum thermal_access_mode thermal_read_mode;
2731
2732
2733
2734static ssize_t thermal_temp_input_show(struct device *dev,
2735 struct device_attribute *attr,
2736 char *buf)
2737{
2738 struct sensor_device_attribute *sensor_attr =
2739 to_sensor_dev_attr(attr);
2740 int idx = sensor_attr->index;
2741 s32 value;
2742 int res;
2743
2744 res = thermal_get_sensor(idx, &value);
2745 if (res)
2746 return res;
2747 if (value == TP_EC_THERMAL_TMP_NA * 1000)
2748 return -ENXIO;
2749
2750 return snprintf(buf, PAGE_SIZE, "%d\n", value);
2751}
2752
2753#define THERMAL_SENSOR_ATTR_TEMP(_idxA, _idxB) \
2754 SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, thermal_temp_input_show, NULL, _idxB)
2755
2756static struct sensor_device_attribute sensor_dev_attr_thermal_temp_input[] = {
2757 THERMAL_SENSOR_ATTR_TEMP(1, 0),
2758 THERMAL_SENSOR_ATTR_TEMP(2, 1),
2759 THERMAL_SENSOR_ATTR_TEMP(3, 2),
2760 THERMAL_SENSOR_ATTR_TEMP(4, 3),
2761 THERMAL_SENSOR_ATTR_TEMP(5, 4),
2762 THERMAL_SENSOR_ATTR_TEMP(6, 5),
2763 THERMAL_SENSOR_ATTR_TEMP(7, 6),
2764 THERMAL_SENSOR_ATTR_TEMP(8, 7),
2765 THERMAL_SENSOR_ATTR_TEMP(9, 8),
2766 THERMAL_SENSOR_ATTR_TEMP(10, 9),
2767 THERMAL_SENSOR_ATTR_TEMP(11, 10),
2768 THERMAL_SENSOR_ATTR_TEMP(12, 11),
2769 THERMAL_SENSOR_ATTR_TEMP(13, 12),
2770 THERMAL_SENSOR_ATTR_TEMP(14, 13),
2771 THERMAL_SENSOR_ATTR_TEMP(15, 14),
2772 THERMAL_SENSOR_ATTR_TEMP(16, 15),
2773};
2774
2775#define THERMAL_ATTRS(X) \
2776 &sensor_dev_attr_thermal_temp_input[X].dev_attr.attr
2777
2778static struct attribute *thermal_temp_input_attr[] = {
2779 THERMAL_ATTRS(8),
2780 THERMAL_ATTRS(9),
2781 THERMAL_ATTRS(10),
2782 THERMAL_ATTRS(11),
2783 THERMAL_ATTRS(12),
2784 THERMAL_ATTRS(13),
2785 THERMAL_ATTRS(14),
2786 THERMAL_ATTRS(15),
2787 THERMAL_ATTRS(0),
2788 THERMAL_ATTRS(1),
2789 THERMAL_ATTRS(2),
2790 THERMAL_ATTRS(3),
2791 THERMAL_ATTRS(4),
2792 THERMAL_ATTRS(5),
2793 THERMAL_ATTRS(6),
2794 THERMAL_ATTRS(7),
2795 NULL
2796};
2797
2798static const struct attribute_group thermal_temp_input16_group = {
2799 .attrs = thermal_temp_input_attr
2800};
2801
2802static const struct attribute_group thermal_temp_input8_group = {
2803 .attrs = &thermal_temp_input_attr[8]
2804};
2805
2806#undef THERMAL_SENSOR_ATTR_TEMP
2807#undef THERMAL_ATTRS
2808
2809
2810
2811static int __init thermal_init(struct ibm_init_struct *iibm)
2812{
2813 u8 t, ta1, ta2;
2814 int i;
2815 int acpi_tmp7;
2816 int res;
2817
2818 vdbg_printk(TPACPI_DBG_INIT, "initializing thermal subdriver\n");
2819
2820 acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
2821
2822 if (thinkpad_id.ec_model) {
2823
2824
2825
2826
2827
2828
2829
2830 ta1 = ta2 = 0;
2831 for (i = 0; i < 8; i++) {
2832 if (acpi_ec_read(TP_EC_THERMAL_TMP0 + i, &t)) {
2833 ta1 |= t;
2834 } else {
2835 ta1 = 0;
2836 break;
2837 }
2838 if (acpi_ec_read(TP_EC_THERMAL_TMP8 + i, &t)) {
2839 ta2 |= t;
2840 } else {
2841 ta1 = 0;
2842 break;
2843 }
2844 }
2845 if (ta1 == 0) {
2846
2847 if (acpi_tmp7) {
2848 printk(IBM_ERR
2849 "ThinkPad ACPI EC access misbehaving, "
2850 "falling back to ACPI TMPx access mode\n");
2851 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
2852 } else {
2853 printk(IBM_ERR
2854 "ThinkPad ACPI EC access misbehaving, "
2855 "disabling thermal sensors access\n");
2856 thermal_read_mode = TPACPI_THERMAL_NONE;
2857 }
2858 } else {
2859 thermal_read_mode =
2860 (ta2 != 0) ?
2861 TPACPI_THERMAL_TPEC_16 : TPACPI_THERMAL_TPEC_8;
2862 }
2863 } else if (acpi_tmp7) {
2864 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
2865
2866 thermal_read_mode = TPACPI_THERMAL_ACPI_UPDT;
2867 } else {
2868
2869 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
2870 }
2871 } else {
2872
2873 thermal_read_mode = TPACPI_THERMAL_NONE;
2874 }
2875
2876 vdbg_printk(TPACPI_DBG_INIT, "thermal is %s, mode %d\n",
2877 str_supported(thermal_read_mode != TPACPI_THERMAL_NONE),
2878 thermal_read_mode);
2879
2880 switch(thermal_read_mode) {
2881 case TPACPI_THERMAL_TPEC_16:
2882 res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
2883 &thermal_temp_input16_group);
2884 if (res)
2885 return res;
2886 break;
2887 case TPACPI_THERMAL_TPEC_8:
2888 case TPACPI_THERMAL_ACPI_TMP07:
2889 case TPACPI_THERMAL_ACPI_UPDT:
2890 res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
2891 &thermal_temp_input8_group);
2892 if (res)
2893 return res;
2894 break;
2895 case TPACPI_THERMAL_NONE:
2896 default:
2897 return 1;
2898 }
2899
2900 return 0;
2901}
2902
2903static void thermal_exit(void)
2904{
2905 switch(thermal_read_mode) {
2906 case TPACPI_THERMAL_TPEC_16:
2907 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
2908 &thermal_temp_input16_group);
2909 break;
2910 case TPACPI_THERMAL_TPEC_8:
2911 case TPACPI_THERMAL_ACPI_TMP07:
2912 case TPACPI_THERMAL_ACPI_UPDT:
2913 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
2914 &thermal_temp_input16_group);
2915 break;
2916 case TPACPI_THERMAL_NONE:
2917 default:
2918 break;
2919 }
2920}
2921
2922
2923static int thermal_get_sensor(int idx, s32 *value)
2924{
2925 int t;
2926 s8 tmp;
2927 char tmpi[5];
2928
2929 t = TP_EC_THERMAL_TMP0;
2930
2931 switch (thermal_read_mode) {
2932#if TPACPI_MAX_THERMAL_SENSORS >= 16
2933 case TPACPI_THERMAL_TPEC_16:
2934 if (idx >= 8 && idx <= 15) {
2935 t = TP_EC_THERMAL_TMP8;
2936 idx -= 8;
2937 }
2938
2939#endif
2940 case TPACPI_THERMAL_TPEC_8:
2941 if (idx <= 7) {
2942 if (!acpi_ec_read(t + idx, &tmp))
2943 return -EIO;
2944 *value = tmp * 1000;
2945 return 0;
2946 }
2947 break;
2948
2949 case TPACPI_THERMAL_ACPI_UPDT:
2950 if (idx <= 7) {
2951 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
2952 if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
2953 return -EIO;
2954 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
2955 return -EIO;
2956 *value = (t - 2732) * 100;
2957 return 0;
2958 }
2959 break;
2960
2961 case TPACPI_THERMAL_ACPI_TMP07:
2962 if (idx <= 7) {
2963 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
2964 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
2965 return -EIO;
2966 if (t > 127 || t < -127)
2967 t = TP_EC_THERMAL_TMP_NA;
2968 *value = t * 1000;
2969 return 0;
2970 }
2971 break;
2972
2973 case TPACPI_THERMAL_NONE:
2974 default:
2975 return -ENOSYS;
2976 }
2977
2978 return -EINVAL;
2979}
2980
2981static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
2982{
2983 int res, i;
2984 int n;
2985
2986 n = 8;
2987 i = 0;
2988
2989 if (!s)
2990 return -EINVAL;
2991
2992 if (thermal_read_mode == TPACPI_THERMAL_TPEC_16)
2993 n = 16;
2994
2995 for(i = 0 ; i < n; i++) {
2996 res = thermal_get_sensor(i, &s->temp[i]);
2997 if (res)
2998 return res;
2999 }
3000
3001 return n;
3002}
3003
3004static int thermal_read(char *p)
3005{
3006 int len = 0;
3007 int n, i;
3008 struct ibm_thermal_sensors_struct t;
3009
3010 n = thermal_get_sensors(&t);
3011 if (unlikely(n < 0))
3012 return n;
3013
3014 len += sprintf(p + len, "temperatures:\t");
3015
3016 if (n > 0) {
3017 for (i = 0; i < (n - 1); i++)
3018 len += sprintf(p + len, "%d ", t.temp[i] / 1000);
3019 len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
3020 } else
3021 len += sprintf(p + len, "not supported\n");
3022
3023 return len;
3024}
3025
3026static struct ibm_struct thermal_driver_data = {
3027 .name = "thermal",
3028 .read = thermal_read,
3029 .exit = thermal_exit,
3030};
3031
3032
3033
3034
3035
3036static u8 ecdump_regs[256];
3037
3038static int ecdump_read(char *p)
3039{
3040 int len = 0;
3041 int i, j;
3042 u8 v;
3043
3044 len += sprintf(p + len, "EC "
3045 " +00 +01 +02 +03 +04 +05 +06 +07"
3046 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
3047 for (i = 0; i < 256; i += 16) {
3048 len += sprintf(p + len, "EC 0x%02x:", i);
3049 for (j = 0; j < 16; j++) {
3050 if (!acpi_ec_read(i + j, &v))
3051 break;
3052 if (v != ecdump_regs[i + j])
3053 len += sprintf(p + len, " *%02x", v);
3054 else
3055 len += sprintf(p + len, " %02x", v);
3056 ecdump_regs[i + j] = v;
3057 }
3058 len += sprintf(p + len, "\n");
3059 if (j != 16)
3060 break;
3061 }
3062
3063
3064#if 0
3065 len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
3066 " (<offset> is 00-ff, <value> is 00-ff)\n");
3067 len += sprintf(p + len, "commands:\t0x<offset> <value> "
3068 " (<offset> is 00-ff, <value> is 0-255)\n");
3069#endif
3070 return len;
3071}
3072
3073static int ecdump_write(char *buf)
3074{
3075 char *cmd;
3076 int i, v;
3077
3078 while ((cmd = next_cmd(&buf))) {
3079 if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
3080
3081 } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
3082
3083 } else
3084 return -EINVAL;
3085 if (i >= 0 && i < 256 && v >= 0 && v < 256) {
3086 if (!acpi_ec_write(i, v))
3087 return -EIO;
3088 } else
3089 return -EINVAL;
3090 }
3091
3092 return 0;
3093}
3094
3095static struct ibm_struct ecdump_driver_data = {
3096 .name = "ecdump",
3097 .read = ecdump_read,
3098 .write = ecdump_write,
3099 .flags.experimental = 1,
3100};
3101
3102
3103
3104
3105
3106static struct backlight_device *ibm_backlight_device;
3107
3108static struct backlight_ops ibm_backlight_data = {
3109 .get_brightness = brightness_get,
3110 .update_status = brightness_update_status,
3111};
3112
3113static struct mutex brightness_mutex;
3114
3115static int __init tpacpi_query_bcll_levels(acpi_handle handle)
3116{
3117 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
3118 union acpi_object *obj;
3119 int rc;
3120
3121 if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
3122 obj = (union acpi_object *)buffer.pointer;
3123 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
3124 printk(IBM_ERR "Unknown BCLL data, "
3125 "please report this to %s\n", IBM_MAIL);
3126 rc = 0;
3127 } else {
3128 rc = obj->package.count;
3129 }
3130 } else {
3131 return 0;
3132 }
3133
3134 kfree(buffer.pointer);
3135 return rc;
3136}
3137
3138static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl,
3139 void *context, void **rv)
3140{
3141 char name[ACPI_PATH_SEGMENT_LENGTH];
3142 struct acpi_buffer buffer = { sizeof(name), &name };
3143
3144 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
3145 !strncmp("BCLL", name, sizeof(name) - 1)) {
3146 if (tpacpi_query_bcll_levels(handle) == 16) {
3147 *rv = handle;
3148 return AE_CTRL_TERMINATE;
3149 } else {
3150 return AE_OK;
3151 }
3152 } else {
3153 return AE_OK;
3154 }
3155}
3156
3157static int __init brightness_check_levels(void)
3158{
3159 int status;
3160 void *found_node = NULL;
3161
3162 if (!vid_handle) {
3163 IBM_ACPIHANDLE_INIT(vid);
3164 }
3165 if (!vid_handle)
3166 return 0;
3167
3168
3169 status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3,
3170 brightness_find_bcll, NULL, &found_node);
3171
3172 return (ACPI_SUCCESS(status) && found_node != NULL);
3173}
3174
3175static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl,
3176 void *context, void **rv)
3177{
3178 char name[ACPI_PATH_SEGMENT_LENGTH];
3179 struct acpi_buffer buffer = { sizeof(name), &name };
3180
3181 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
3182 !strncmp("_BCL", name, sizeof(name) - 1)) {
3183 *rv = handle;
3184 return AE_CTRL_TERMINATE;
3185 } else {
3186 return AE_OK;
3187 }
3188}
3189
3190static int __init brightness_check_std_acpi_support(void)
3191{
3192 int status;
3193 void *found_node = NULL;
3194
3195 if (!vid_handle) {
3196 IBM_ACPIHANDLE_INIT(vid);
3197 }
3198 if (!vid_handle)
3199 return 0;
3200
3201
3202 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
3203 brightness_find_bcl, NULL, &found_node);
3204
3205 return (ACPI_SUCCESS(status) && found_node != NULL);
3206}
3207
3208static int __init brightness_init(struct ibm_init_struct *iibm)
3209{
3210 int b;
3211
3212 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n");
3213
3214 mutex_init(&brightness_mutex);
3215
3216 if (!brightness_enable) {
3217 dbg_printk(TPACPI_DBG_INIT,
3218 "brightness support disabled by module parameter\n");
3219 return 1;
3220 } else if (brightness_enable > 1) {
3221 if (brightness_check_std_acpi_support()) {
3222 printk(IBM_NOTICE
3223 "standard ACPI backlight interface available, not loading native one...\n");
3224 return 1;
3225 }
3226 }
3227
3228 if (!brightness_mode) {
3229 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO)
3230 brightness_mode = 2;
3231 else
3232 brightness_mode = 3;
3233
3234 dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n",
3235 brightness_mode);
3236 }
3237
3238 if (brightness_mode > 3)
3239 return -EINVAL;
3240
3241 tp_features.bright_16levels =
3242 thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO &&
3243 brightness_check_levels();
3244
3245 b = brightness_get(NULL);
3246 if (b < 0)
3247 return 1;
3248
3249 if (tp_features.bright_16levels)
3250 printk(IBM_INFO "detected a 16-level brightness capable ThinkPad\n");
3251
3252 ibm_backlight_device = backlight_device_register(
3253 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
3254 &ibm_backlight_data);
3255 if (IS_ERR(ibm_backlight_device)) {
3256 printk(IBM_ERR "Could not register backlight device\n");
3257 return PTR_ERR(ibm_backlight_device);
3258 }
3259 vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n");
3260
3261 ibm_backlight_device->props.max_brightness =
3262 (tp_features.bright_16levels)? 15 : 7;
3263 ibm_backlight_device->props.brightness = b;
3264 backlight_update_status(ibm_backlight_device);
3265
3266 return 0;
3267}
3268
3269static void brightness_exit(void)
3270{
3271 if (ibm_backlight_device) {
3272 vdbg_printk(TPACPI_DBG_EXIT,
3273 "calling backlight_device_unregister()\n");
3274 backlight_device_unregister(ibm_backlight_device);
3275 ibm_backlight_device = NULL;
3276 }
3277}
3278
3279static int brightness_update_status(struct backlight_device *bd)
3280{
3281
3282
3283 return brightness_set(
3284 (bd->props.fb_blank == FB_BLANK_UNBLANK &&
3285 bd->props.power == FB_BLANK_UNBLANK) ?
3286 bd->props.brightness : 0);
3287}
3288
3289
3290
3291
3292
3293static int brightness_get(struct backlight_device *bd)
3294{
3295 u8 lec = 0, lcmos = 0, level = 0;
3296
3297 if (brightness_mode & 1) {
3298 if (!acpi_ec_read(brightness_offset, &lec))
3299 return -EIO;
3300 lec &= (tp_features.bright_16levels)? 0x0f : 0x07;
3301 level = lec;
3302 };
3303 if (brightness_mode & 2) {
3304 lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
3305 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
3306 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
3307 lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07;
3308 level = lcmos;
3309 }
3310
3311 if (brightness_mode == 3 && lec != lcmos) {
3312 printk(IBM_ERR
3313 "CMOS NVRAM (%u) and EC (%u) do not agree "
3314 "on display brightness level\n",
3315 (unsigned int) lcmos,
3316 (unsigned int) lec);
3317 return -EIO;
3318 }
3319
3320 return level;
3321}
3322
3323
3324static int brightness_set(int value)
3325{
3326 int cmos_cmd, inc, i, res;
3327 int current_value;
3328
3329 if (value > ((tp_features.bright_16levels)? 15 : 7))
3330 return -EINVAL;
3331
3332 res = mutex_lock_interruptible(&brightness_mutex);
3333 if (res < 0)
3334 return res;
3335
3336 current_value = brightness_get(NULL);
3337 if (current_value < 0) {
3338 res = current_value;
3339 goto errout;
3340 }
3341
3342 cmos_cmd = value > current_value ?
3343 TP_CMOS_BRIGHTNESS_UP :
3344 TP_CMOS_BRIGHTNESS_DOWN;
3345 inc = (value > current_value)? 1 : -1;
3346
3347 res = 0;
3348 for (i = current_value; i != value; i += inc) {
3349 if ((brightness_mode & 2) &&
3350 issue_thinkpad_cmos_command(cmos_cmd)) {
3351 res = -EIO;
3352 goto errout;
3353 }
3354 if ((brightness_mode & 1) &&
3355 !acpi_ec_write(brightness_offset, i + inc)) {
3356 res = -EIO;
3357 goto errout;;
3358 }
3359 }
3360
3361errout:
3362 mutex_unlock(&brightness_mutex);
3363 return res;
3364}
3365
3366static int brightness_read(char *p)
3367{
3368 int len = 0;
3369 int level;
3370
3371 if ((level = brightness_get(NULL)) < 0) {
3372 len += sprintf(p + len, "level:\t\tunreadable\n");
3373 } else {
3374 len += sprintf(p + len, "level:\t\t%d\n", level);
3375 len += sprintf(p + len, "commands:\tup, down\n");
3376 len += sprintf(p + len, "commands:\tlevel <level>"
3377 " (<level> is 0-%d)\n",
3378 (tp_features.bright_16levels) ? 15 : 7);
3379 }
3380
3381 return len;
3382}
3383
3384static int brightness_write(char *buf)
3385{
3386 int level;
3387 int rc;
3388 char *cmd;
3389 int max_level = (tp_features.bright_16levels) ? 15 : 7;
3390
3391 level = brightness_get(NULL);
3392 if (level < 0)
3393 return level;
3394
3395 while ((cmd = next_cmd(&buf))) {
3396 if (strlencmp(cmd, "up") == 0) {
3397 if (level < max_level)
3398 level++;
3399 } else if (strlencmp(cmd, "down") == 0) {
3400 if (level > 0)
3401 level--;
3402 } else if (sscanf(cmd, "level %d", &level) == 1 &&
3403 level >= 0 && level <= max_level) {
3404
3405 } else
3406 return -EINVAL;
3407 }
3408
3409
3410
3411
3412
3413 rc = brightness_set(level);
3414 return (rc == -EINTR)? ERESTARTSYS : rc;
3415}
3416
3417static struct ibm_struct brightness_driver_data = {
3418 .name = "brightness",
3419 .read = brightness_read,
3420 .write = brightness_write,
3421 .exit = brightness_exit,
3422};
3423
3424
3425
3426
3427
3428static int volume_read(char *p)
3429{
3430 int len = 0;
3431 u8 level;
3432
3433 if (!acpi_ec_read(volume_offset, &level)) {
3434 len += sprintf(p + len, "level:\t\tunreadable\n");
3435 } else {
3436 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
3437 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
3438 len += sprintf(p + len, "commands:\tup, down, mute\n");
3439 len += sprintf(p + len, "commands:\tlevel <level>"
3440 " (<level> is 0-15)\n");
3441 }
3442
3443 return len;
3444}
3445
3446static int volume_write(char *buf)
3447{
3448 int cmos_cmd, inc, i;
3449 u8 level, mute;
3450 int new_level, new_mute;
3451 char *cmd;
3452
3453 while ((cmd = next_cmd(&buf))) {
3454 if (!acpi_ec_read(volume_offset, &level))
3455 return -EIO;
3456 new_mute = mute = level & 0x40;
3457 new_level = level = level & 0xf;
3458
3459 if (strlencmp(cmd, "up") == 0) {
3460 if (mute)
3461 new_mute = 0;
3462 else
3463 new_level = level == 15 ? 15 : level + 1;
3464 } else if (strlencmp(cmd, "down") == 0) {
3465 if (mute)
3466 new_mute = 0;
3467 else
3468 new_level = level == 0 ? 0 : level - 1;
3469 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
3470 new_level >= 0 && new_level <= 15) {
3471
3472 } else if (strlencmp(cmd, "mute") == 0) {
3473 new_mute = 0x40;
3474 } else
3475 return -EINVAL;
3476
3477 if (new_level != level) {
3478 cmos_cmd = new_level > level ? TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN;
3479 inc = new_level > level ? 1 : -1;
3480
3481 if (mute && (issue_thinkpad_cmos_command(cmos_cmd) ||
3482 !acpi_ec_write(volume_offset, level)))
3483 return -EIO;
3484
3485 for (i = level; i != new_level; i += inc)
3486 if (issue_thinkpad_cmos_command(cmos_cmd) ||
3487 !acpi_ec_write(volume_offset, i + inc))
3488 return -EIO;
3489
3490 if (mute && (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) ||
3491 !acpi_ec_write(volume_offset,
3492 new_level + mute)))
3493 return -EIO;
3494 }
3495
3496 if (new_mute != mute) {
3497 cmos_cmd = new_mute ? TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP;
3498
3499 if (issue_thinkpad_cmos_command(cmos_cmd) ||
3500 !acpi_ec_write(volume_offset, level + new_mute))
3501 return -EIO;
3502 }
3503 }
3504
3505 return 0;
3506}
3507
3508static struct ibm_struct volume_driver_data = {
3509 .name = "volume",
3510 .read = volume_read,
3511 .write = volume_write,
3512};
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619static enum fan_status_access_mode fan_status_access_mode;
3620static enum fan_control_access_mode fan_control_access_mode;
3621static enum fan_control_commands fan_control_commands;
3622
3623static u8 fan_control_initial_status;
3624static u8 fan_control_desired_level;
3625
3626static void fan_watchdog_fire(struct work_struct *ignored);
3627static int fan_watchdog_maxinterval;
3628static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
3629
3630IBM_HANDLE(fans, ec, "FANS");
3631IBM_HANDLE(gfan, ec, "GFAN",
3632 "\\FSPD",
3633 );
3634IBM_HANDLE(sfan, ec, "SFAN",
3635 "JFNS",
3636 );
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660static ssize_t fan_pwm1_enable_show(struct device *dev,
3661 struct device_attribute *attr,
3662 char *buf)
3663{
3664 int res, mode;
3665 u8 status;
3666
3667 res = fan_get_status_safe(&status);
3668 if (res)
3669 return res;
3670
3671 if (unlikely(tp_features.fan_ctrl_status_undef)) {
3672 if (status != fan_control_initial_status) {
3673 tp_features.fan_ctrl_status_undef = 0;
3674 } else {
3675
3676
3677 status = TP_EC_FAN_AUTO;
3678 }
3679 }
3680
3681 if (status & TP_EC_FAN_FULLSPEED) {
3682 mode = 0;
3683 } else if (status & TP_EC_FAN_AUTO) {
3684 mode = 2;
3685 } else
3686 mode = 1;
3687
3688 return snprintf(buf, PAGE_SIZE, "%d\n", mode);
3689}
3690
3691static ssize_t fan_pwm1_enable_store(struct device *dev,
3692 struct device_attribute *attr,
3693 const char *buf, size_t count)
3694{
3695 unsigned long t;
3696 int res, level;
3697
3698 if (parse_strtoul(buf, 2, &t))
3699 return -EINVAL;
3700
3701 switch (t) {
3702 case 0:
3703 level = TP_EC_FAN_FULLSPEED;
3704 break;
3705 case 1:
3706 level = TPACPI_FAN_LAST_LEVEL;
3707 break;
3708 case 2:
3709 level = TP_EC_FAN_AUTO;
3710 break;
3711 case 3:
3712
3713 return -ENOSYS;
3714 default:
3715 return -EINVAL;
3716 }
3717
3718 res = fan_set_level_safe(level);
3719 if (res == -ENXIO)
3720 return -EINVAL;
3721 else if (res < 0)
3722 return res;
3723
3724 fan_watchdog_reset();
3725
3726 return count;
3727}
3728
3729static struct device_attribute dev_attr_fan_pwm1_enable =
3730 __ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
3731 fan_pwm1_enable_show, fan_pwm1_enable_store);
3732
3733
3734static ssize_t fan_pwm1_show(struct device *dev,
3735 struct device_attribute *attr,
3736 char *buf)
3737{
3738 int res;
3739 u8 status;
3740
3741 res = fan_get_status_safe(&status);
3742 if (res)
3743 return res;
3744
3745 if (unlikely(tp_features.fan_ctrl_status_undef)) {
3746 if (status != fan_control_initial_status) {
3747 tp_features.fan_ctrl_status_undef = 0;
3748 } else {
3749 status = TP_EC_FAN_AUTO;
3750 }
3751 }
3752
3753 if ((status &
3754 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0)
3755 status = fan_control_desired_level;
3756
3757 if (status > 7)
3758 status = 7;
3759
3760 return snprintf(buf, PAGE_SIZE, "%u\n", (status * 255) / 7);
3761}
3762
3763static ssize_t fan_pwm1_store(struct device *dev,
3764 struct device_attribute *attr,
3765 const char *buf, size_t count)
3766{
3767 unsigned long s;
3768 int rc;
3769 u8 status, newlevel;
3770
3771 if (parse_strtoul(buf, 255, &s))
3772 return -EINVAL;
3773
3774
3775 newlevel = (s >> 5) & 0x07;
3776
3777 if (mutex_lock_interruptible(&fan_mutex))
3778 return -ERESTARTSYS;
3779
3780 rc = fan_get_status(&status);
3781 if (!rc && (status &
3782 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
3783 rc = fan_set_level(newlevel);
3784 if (rc == -ENXIO)
3785 rc = -EINVAL;
3786 else if (!rc) {
3787 fan_update_desired_level(newlevel);
3788 fan_watchdog_reset();
3789 }
3790 }
3791
3792 mutex_unlock(&fan_mutex);
3793 return (rc)? rc : count;
3794}
3795
3796static struct device_attribute dev_attr_fan_pwm1 =
3797 __ATTR(pwm1, S_IWUSR | S_IRUGO,
3798 fan_pwm1_show, fan_pwm1_store);
3799
3800
3801static ssize_t fan_fan1_input_show(struct device *dev,
3802 struct device_attribute *attr,
3803 char *buf)
3804{
3805 int res;
3806 unsigned int speed;
3807
3808 res = fan_get_speed(&speed);
3809 if (res < 0)
3810 return res;
3811
3812 return snprintf(buf, PAGE_SIZE, "%u\n", speed);
3813}
3814
3815static struct device_attribute dev_attr_fan_fan1_input =
3816 __ATTR(fan1_input, S_IRUGO,
3817 fan_fan1_input_show, NULL);
3818
3819
3820static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
3821 char *buf)
3822{
3823 return snprintf(buf, PAGE_SIZE, "%u\n", fan_watchdog_maxinterval);
3824}
3825
3826static ssize_t fan_fan_watchdog_store(struct device_driver *drv,
3827 const char *buf, size_t count)
3828{
3829 unsigned long t;
3830
3831 if (parse_strtoul(buf, 120, &t))
3832 return -EINVAL;
3833
3834 if (!fan_control_allowed)
3835 return -EPERM;
3836
3837 fan_watchdog_maxinterval = t;
3838 fan_watchdog_reset();
3839
3840 return count;
3841}
3842
3843static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO,
3844 fan_fan_watchdog_show, fan_fan_watchdog_store);
3845
3846
3847static struct attribute *fan_attributes[] = {
3848 &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr,
3849 &dev_attr_fan_fan1_input.attr,
3850 NULL
3851};
3852
3853static const struct attribute_group fan_attr_group = {
3854 .attrs = fan_attributes,
3855};
3856
3857static int __init fan_init(struct ibm_init_struct *iibm)
3858{
3859 int rc;
3860
3861 vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n");
3862
3863 mutex_init(&fan_mutex);
3864 fan_status_access_mode = TPACPI_FAN_NONE;
3865 fan_control_access_mode = TPACPI_FAN_WR_NONE;
3866 fan_control_commands = 0;
3867 fan_watchdog_maxinterval = 0;
3868 tp_features.fan_ctrl_status_undef = 0;
3869 fan_control_desired_level = 7;
3870
3871 IBM_ACPIHANDLE_INIT(fans);
3872 IBM_ACPIHANDLE_INIT(gfan);
3873 IBM_ACPIHANDLE_INIT(sfan);
3874
3875 if (gfan_handle) {
3876
3877 fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
3878 } else {
3879
3880
3881 if (likely(acpi_ec_read(fan_status_offset,
3882 &fan_control_initial_status))) {
3883 fan_status_access_mode = TPACPI_FAN_RD_TPEC;
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893 if (fan_control_initial_status == 0x07) {
3894 switch (thinkpad_id.ec_model) {
3895 case 0x5931:
3896 case 0x3837:
3897 case 0x3637:
3898 case 0x3037:
3899 printk(IBM_NOTICE
3900 "fan_init: initial fan status is "
3901 "unknown, assuming it is in auto "
3902 "mode\n");
3903 tp_features.fan_ctrl_status_undef = 1;
3904 ;;
3905 }
3906 }
3907 } else {
3908 printk(IBM_ERR
3909 "ThinkPad ACPI EC access misbehaving, "
3910 "fan status and control unavailable\n");
3911 return 1;
3912 }
3913 }
3914
3915 if (sfan_handle) {
3916
3917 fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN;
3918 fan_control_commands |=
3919 TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_ENABLE;
3920 } else {
3921 if (!gfan_handle) {
3922
3923
3924
3925 if (fans_handle) {
3926
3927 fan_control_access_mode =
3928 TPACPI_FAN_WR_ACPI_FANS;
3929 fan_control_commands |=
3930 TPACPI_FAN_CMD_SPEED |
3931 TPACPI_FAN_CMD_LEVEL |
3932 TPACPI_FAN_CMD_ENABLE;
3933 } else {
3934 fan_control_access_mode = TPACPI_FAN_WR_TPEC;
3935 fan_control_commands |=
3936 TPACPI_FAN_CMD_LEVEL |
3937 TPACPI_FAN_CMD_ENABLE;
3938 }
3939 }
3940 }
3941
3942 vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n",
3943 str_supported(fan_status_access_mode != TPACPI_FAN_NONE ||
3944 fan_control_access_mode != TPACPI_FAN_WR_NONE),
3945 fan_status_access_mode, fan_control_access_mode);
3946
3947
3948 if (!fan_control_allowed) {
3949 fan_control_access_mode = TPACPI_FAN_WR_NONE;
3950 fan_control_commands = 0;
3951 dbg_printk(TPACPI_DBG_INIT,
3952 "fan control features disabled by parameter\n");
3953 }
3954
3955
3956 if (fan_status_access_mode != TPACPI_FAN_NONE)
3957 fan_get_status_safe(NULL);
3958
3959 if (fan_status_access_mode != TPACPI_FAN_NONE ||
3960 fan_control_access_mode != TPACPI_FAN_WR_NONE) {
3961 rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
3962 &fan_attr_group);
3963 if (!(rc < 0))
3964 rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
3965 &driver_attr_fan_watchdog);
3966 if (rc < 0)
3967 return rc;
3968 return 0;
3969 } else
3970 return 1;
3971}
3972
3973
3974
3975
3976static void fan_update_desired_level(u8 status)
3977{
3978 if ((status &
3979 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
3980 if (status > 7)
3981 fan_control_desired_level = 7;
3982 else
3983 fan_control_desired_level = status;
3984 }
3985}
3986
3987static int fan_get_status(u8 *status)
3988{
3989 u8 s;
3990
3991
3992
3993
3994 switch (fan_status_access_mode) {
3995 case TPACPI_FAN_RD_ACPI_GFAN:
3996
3997
3998 if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
3999 return -EIO;
4000
4001 if (likely(status))
4002 *status = s & 0x07;
4003
4004 break;
4005
4006 case TPACPI_FAN_RD_TPEC:
4007
4008 if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
4009 return -EIO;
4010
4011 if (likely(status))
4012 *status = s;
4013
4014 break;
4015
4016 default:
4017 return -ENXIO;
4018 }
4019
4020 return 0;
4021}
4022
4023static int fan_get_status_safe(u8 *status)
4024{
4025 int rc;
4026 u8 s;
4027
4028 if (mutex_lock_interruptible(&fan_mutex))
4029 return -ERESTARTSYS;
4030 rc = fan_get_status(&s);
4031 if (!rc)
4032 fan_update_desired_level(s);
4033 mutex_unlock(&fan_mutex);
4034
4035 if (status)
4036 *status = s;
4037
4038 return rc;
4039}
4040
4041static void fan_exit(void)
4042{
4043 vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n");
4044
4045
4046 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group);
4047 driver_remove_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog);
4048
4049 cancel_delayed_work(&fan_watchdog_task);
4050 flush_scheduled_work();
4051}
4052
4053static int fan_get_speed(unsigned int *speed)
4054{
4055 u8 hi, lo;
4056
4057 switch (fan_status_access_mode) {
4058 case TPACPI_FAN_RD_TPEC:
4059
4060 if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
4061 !acpi_ec_read(fan_rpm_offset + 1, &hi)))
4062 return -EIO;
4063
4064 if (likely(speed))
4065 *speed = (hi << 8) | lo;
4066
4067 break;
4068
4069 default:
4070 return -ENXIO;
4071 }
4072
4073 return 0;
4074}
4075
4076static void fan_watchdog_fire(struct work_struct *ignored)
4077{
4078 int rc;
4079
4080 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
4081 return;
4082
4083 printk(IBM_NOTICE "fan watchdog: enabling fan\n");
4084 rc = fan_set_enable();
4085 if (rc < 0) {
4086 printk(IBM_ERR "fan watchdog: error %d while enabling fan, "
4087 "will try again later...\n", -rc);
4088
4089 fan_watchdog_reset();
4090 }
4091}
4092
4093static void fan_watchdog_reset(void)
4094{
4095 static int fan_watchdog_active;
4096
4097 if (fan_control_access_mode == TPACPI_FAN_WR_NONE)
4098 return;
4099
4100 if (fan_watchdog_active)
4101 cancel_delayed_work(&fan_watchdog_task);
4102
4103 if (fan_watchdog_maxinterval > 0 &&
4104 tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
4105 fan_watchdog_active = 1;
4106 if (!schedule_delayed_work(&fan_watchdog_task,
4107 msecs_to_jiffies(fan_watchdog_maxinterval
4108 * 1000))) {
4109 printk(IBM_ERR "failed to schedule the fan watchdog, "
4110 "watchdog will not trigger\n");
4111 }
4112 } else
4113 fan_watchdog_active = 0;
4114}
4115
4116static int fan_set_level(int level)
4117{
4118 if (!fan_control_allowed)
4119 return -EPERM;
4120
4121 switch (fan_control_access_mode) {
4122 case TPACPI_FAN_WR_ACPI_SFAN:
4123 if (level >= 0 && level <= 7) {
4124 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
4125 return -EIO;
4126 } else
4127 return -EINVAL;
4128 break;
4129
4130 case TPACPI_FAN_WR_ACPI_FANS:
4131 case TPACPI_FAN_WR_TPEC:
4132 if ((level != TP_EC_FAN_AUTO) &&
4133 (level != TP_EC_FAN_FULLSPEED) &&
4134 ((level < 0) || (level > 7)))
4135 return -EINVAL;
4136
4137
4138
4139 if (level & TP_EC_FAN_FULLSPEED)
4140 level |= 7;
4141 else if (level & TP_EC_FAN_FULLSPEED)
4142 level |= 4;
4143
4144 if (!acpi_ec_write(fan_status_offset, level))
4145 return -EIO;
4146 else
4147 tp_features.fan_ctrl_status_undef = 0;
4148 break;
4149
4150 default:
4151 return -ENXIO;
4152 }
4153 return 0;
4154}
4155
4156static int fan_set_level_safe(int level)
4157{
4158 int rc;
4159
4160 if (!fan_control_allowed)
4161 return -EPERM;
4162
4163 if (mutex_lock_interruptible(&fan_mutex))
4164 return -ERESTARTSYS;
4165
4166 if (level == TPACPI_FAN_LAST_LEVEL)
4167 level = fan_control_desired_level;
4168
4169 rc = fan_set_level(level);
4170 if (!rc)
4171 fan_update_desired_level(level);
4172
4173 mutex_unlock(&fan_mutex);
4174 return rc;
4175}
4176
4177static int fan_set_enable(void)
4178{
4179 u8 s;
4180 int rc;
4181
4182 if (!fan_control_allowed)
4183 return -EPERM;
4184
4185 if (mutex_lock_interruptible(&fan_mutex))
4186 return -ERESTARTSYS;
4187
4188 switch (fan_control_access_mode) {
4189 case TPACPI_FAN_WR_ACPI_FANS:
4190 case TPACPI_FAN_WR_TPEC:
4191 rc = fan_get_status(&s);
4192 if (rc < 0)
4193 break;
4194
4195
4196 if (s != 7) {
4197 s &= 0x07;
4198 s |= TP_EC_FAN_AUTO | 4;
4199 }
4200
4201 if (!acpi_ec_write(fan_status_offset, s))
4202 rc = -EIO;
4203 else {
4204 tp_features.fan_ctrl_status_undef = 0;
4205 rc = 0;
4206 }
4207 break;
4208
4209 case TPACPI_FAN_WR_ACPI_SFAN:
4210 rc = fan_get_status(&s);
4211 if (rc < 0)
4212 break;
4213
4214 s &= 0x07;
4215
4216
4217 s |= 4;
4218
4219 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
4220 rc= -EIO;
4221 else
4222 rc = 0;
4223 break;
4224
4225 default:
4226 rc = -ENXIO;
4227 }
4228
4229 mutex_unlock(&fan_mutex);
4230 return rc;
4231}
4232
4233static int fan_set_disable(void)
4234{
4235 int rc;
4236
4237 if (!fan_control_allowed)
4238 return -EPERM;
4239
4240 if (mutex_lock_interruptible(&fan_mutex))
4241 return -ERESTARTSYS;
4242
4243 rc = 0;
4244 switch (fan_control_access_mode) {
4245 case TPACPI_FAN_WR_ACPI_FANS:
4246 case TPACPI_FAN_WR_TPEC:
4247 if (!acpi_ec_write(fan_status_offset, 0x00))
4248 rc = -EIO;
4249 else {
4250 fan_control_desired_level = 0;
4251 tp_features.fan_ctrl_status_undef = 0;
4252 }
4253 break;
4254
4255 case TPACPI_FAN_WR_ACPI_SFAN:
4256 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
4257 rc = -EIO;
4258 else
4259 fan_control_desired_level = 0;
4260 break;
4261
4262 default:
4263 rc = -ENXIO;
4264 }
4265
4266
4267 mutex_unlock(&fan_mutex);
4268 return rc;
4269}
4270
4271static int fan_set_speed(int speed)
4272{
4273 int rc;
4274
4275 if (!fan_control_allowed)
4276 return -EPERM;
4277
4278 if (mutex_lock_interruptible(&fan_mutex))
4279 return -ERESTARTSYS;
4280
4281 rc = 0;
4282 switch (fan_control_access_mode) {
4283 case TPACPI_FAN_WR_ACPI_FANS:
4284 if (speed >= 0 && speed <= 65535) {
4285 if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
4286 speed, speed, speed))
4287 rc = -EIO;
4288 } else
4289 rc = -EINVAL;
4290 break;
4291
4292 default:
4293 rc = -ENXIO;
4294 }
4295
4296 mutex_unlock(&fan_mutex);
4297 return rc;
4298}
4299
4300static int fan_read(char *p)
4301{
4302 int len = 0;
4303 int rc;
4304 u8 status;
4305 unsigned int speed = 0;
4306
4307 switch (fan_status_access_mode) {
4308 case TPACPI_FAN_RD_ACPI_GFAN:
4309
4310 if ((rc = fan_get_status_safe(&status)) < 0)
4311 return rc;
4312
4313 len += sprintf(p + len, "status:\t\t%s\n"
4314 "level:\t\t%d\n",
4315 (status != 0) ? "enabled" : "disabled", status);
4316 break;
4317
4318 case TPACPI_FAN_RD_TPEC:
4319
4320 if ((rc = fan_get_status_safe(&status)) < 0)
4321 return rc;
4322
4323 if (unlikely(tp_features.fan_ctrl_status_undef)) {
4324 if (status != fan_control_initial_status)
4325 tp_features.fan_ctrl_status_undef = 0;
4326 else
4327
4328
4329 status = TP_EC_FAN_AUTO;
4330 }
4331
4332 len += sprintf(p + len, "status:\t\t%s\n",
4333 (status != 0) ? "enabled" : "disabled");
4334
4335 if ((rc = fan_get_speed(&speed)) < 0)
4336 return rc;
4337
4338 len += sprintf(p + len, "speed:\t\t%d\n", speed);
4339
4340 if (status & TP_EC_FAN_FULLSPEED)
4341
4342 len += sprintf(p + len, "level:\t\tdisengaged\n");
4343 else if (status & TP_EC_FAN_AUTO)
4344 len += sprintf(p + len, "level:\t\tauto\n");
4345 else
4346 len += sprintf(p + len, "level:\t\t%d\n", status);
4347 break;
4348
4349 case TPACPI_FAN_NONE:
4350 default:
4351 len += sprintf(p + len, "status:\t\tnot supported\n");
4352 }
4353
4354 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
4355 len += sprintf(p + len, "commands:\tlevel <level>");
4356
4357 switch (fan_control_access_mode) {
4358 case TPACPI_FAN_WR_ACPI_SFAN:
4359 len += sprintf(p + len, " (<level> is 0-7)\n");
4360 break;
4361
4362 default:
4363 len += sprintf(p + len, " (<level> is 0-7, "
4364 "auto, disengaged, full-speed)\n");
4365 break;
4366 }
4367 }
4368
4369 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
4370 len += sprintf(p + len, "commands:\tenable, disable\n"
4371 "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
4372 "1-120 (seconds))\n");
4373
4374 if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
4375 len += sprintf(p + len, "commands:\tspeed <speed>"
4376 " (<speed> is 0-65535)\n");
4377
4378 return len;
4379}
4380
4381static int fan_write_cmd_level(const char *cmd, int *rc)
4382{
4383 int level;
4384
4385 if (strlencmp(cmd, "level auto") == 0)
4386 level = TP_EC_FAN_AUTO;
4387 else if ((strlencmp(cmd, "level disengaged") == 0) |
4388 (strlencmp(cmd, "level full-speed") == 0))
4389 level = TP_EC_FAN_FULLSPEED;
4390 else if (sscanf(cmd, "level %d", &level) != 1)
4391 return 0;
4392
4393 if ((*rc = fan_set_level_safe(level)) == -ENXIO)
4394 printk(IBM_ERR "level command accepted for unsupported "
4395 "access mode %d", fan_control_access_mode);
4396
4397 return 1;
4398}
4399
4400static int fan_write_cmd_enable(const char *cmd, int *rc)
4401{
4402 if (strlencmp(cmd, "enable") != 0)
4403 return 0;
4404
4405 if ((*rc = fan_set_enable()) == -ENXIO)
4406 printk(IBM_ERR "enable command accepted for unsupported "
4407 "access mode %d", fan_control_access_mode);
4408
4409 return 1;
4410}
4411
4412static int fan_write_cmd_disable(const char *cmd, int *rc)
4413{
4414 if (strlencmp(cmd, "disable") != 0)
4415 return 0;
4416
4417 if ((*rc = fan_set_disable()) == -ENXIO)
4418 printk(IBM_ERR "disable command accepted for unsupported "
4419 "access mode %d", fan_control_access_mode);
4420
4421 return 1;
4422}
4423
4424static int fan_write_cmd_speed(const char *cmd, int *rc)
4425{
4426 int speed;
4427
4428
4429
4430
4431 if (sscanf(cmd, "speed %d", &speed) != 1)
4432 return 0;
4433
4434 if ((*rc = fan_set_speed(speed)) == -ENXIO)
4435 printk(IBM_ERR "speed command accepted for unsupported "
4436 "access mode %d", fan_control_access_mode);
4437
4438 return 1;
4439}
4440
4441static int fan_write_cmd_watchdog(const char *cmd, int *rc)
4442{
4443 int interval;
4444
4445 if (sscanf(cmd, "watchdog %d", &interval) != 1)
4446 return 0;
4447
4448 if (interval < 0 || interval > 120)
4449 *rc = -EINVAL;
4450 else
4451 fan_watchdog_maxinterval = interval;
4452
4453 return 1;
4454}
4455
4456static int fan_write(char *buf)
4457{
4458 char *cmd;
4459 int rc = 0;
4460
4461 while (!rc && (cmd = next_cmd(&buf))) {
4462 if (!((fan_control_commands & TPACPI_FAN_CMD_LEVEL) &&
4463 fan_write_cmd_level(cmd, &rc)) &&
4464 !((fan_control_commands & TPACPI_FAN_CMD_ENABLE) &&
4465 (fan_write_cmd_enable(cmd, &rc) ||
4466 fan_write_cmd_disable(cmd, &rc) ||
4467 fan_write_cmd_watchdog(cmd, &rc))) &&
4468 !((fan_control_commands & TPACPI_FAN_CMD_SPEED) &&
4469 fan_write_cmd_speed(cmd, &rc))
4470 )
4471 rc = -EINVAL;
4472 else if (!rc)
4473 fan_watchdog_reset();
4474 }
4475
4476 return rc;
4477}
4478
4479static struct ibm_struct fan_driver_data = {
4480 .name = "fan",
4481 .read = fan_read,
4482 .write = fan_write,
4483 .exit = fan_exit,
4484};
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev,
4496 struct device_attribute *attr,
4497 char *buf)
4498{
4499 return snprintf(buf, PAGE_SIZE, "%s\n", IBM_NAME);
4500}
4501
4502static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
4503 __ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL);
4504
4505
4506
4507
4508static struct proc_dir_entry *proc_dir;
4509
4510
4511static LIST_HEAD(tpacpi_all_drivers);
4512
4513
4514
4515
4516
4517
4518#ifdef CONFIG_THINKPAD_ACPI_DEBUG
4519static const char * __init str_supported(int is_supported)
4520{
4521 static char text_unsupported[] __initdata = "not supported";
4522
4523 return (is_supported)? &text_unsupported[4] : &text_unsupported[0];
4524}
4525#endif
4526
4527static int __init ibm_init(struct ibm_init_struct *iibm)
4528{
4529 int ret;
4530 struct ibm_struct *ibm = iibm->data;
4531 struct proc_dir_entry *entry;
4532
4533 BUG_ON(ibm == NULL);
4534
4535 INIT_LIST_HEAD(&ibm->all_drivers);
4536
4537 if (ibm->flags.experimental && !experimental)
4538 return 0;
4539
4540 dbg_printk(TPACPI_DBG_INIT,
4541 "probing for %s\n", ibm->name);
4542
4543 if (iibm->init) {
4544 ret = iibm->init(iibm);
4545 if (ret > 0)
4546 return 0;
4547 if (ret)
4548 return ret;
4549
4550 ibm->flags.init_called = 1;
4551 }
4552
4553 if (ibm->acpi) {
4554 if (ibm->acpi->hid) {
4555 ret = register_tpacpi_subdriver(ibm);
4556 if (ret)
4557 goto err_out;
4558 }
4559
4560 if (ibm->acpi->notify) {
4561 ret = setup_acpi_notify(ibm);
4562 if (ret == -ENODEV) {
4563 printk(IBM_NOTICE "disabling subdriver %s\n",
4564 ibm->name);
4565 ret = 0;
4566 goto err_out;
4567 }
4568 if (ret < 0)
4569 goto err_out;
4570 }
4571 }
4572
4573 dbg_printk(TPACPI_DBG_INIT,
4574 "%s installed\n", ibm->name);
4575
4576 if (ibm->read) {
4577 entry = create_proc_entry(ibm->name,
4578 S_IFREG | S_IRUGO | S_IWUSR,
4579 proc_dir);
4580 if (!entry) {
4581 printk(IBM_ERR "unable to create proc entry %s\n",
4582 ibm->name);
4583 ret = -ENODEV;
4584 goto err_out;
4585 }
4586 entry->owner = THIS_MODULE;
4587 entry->data = ibm;
4588 entry->read_proc = &dispatch_procfs_read;
4589 if (ibm->write)
4590 entry->write_proc = &dispatch_procfs_write;
4591 ibm->flags.proc_created = 1;
4592 }
4593
4594 list_add_tail(&ibm->all_drivers, &tpacpi_all_drivers);
4595
4596 return 0;
4597
4598err_out:
4599 dbg_printk(TPACPI_DBG_INIT,
4600 "%s: at error exit path with result %d\n",
4601 ibm->name, ret);
4602
4603 ibm_exit(ibm);
4604 return (ret < 0)? ret : 0;
4605}
4606
4607static void ibm_exit(struct ibm_struct *ibm)
4608{
4609 dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name);
4610
4611 list_del_init(&ibm->all_drivers);
4612
4613 if (ibm->flags.acpi_notify_installed) {
4614 dbg_printk(TPACPI_DBG_EXIT,
4615 "%s: acpi_remove_notify_handler\n", ibm->name);
4616 BUG_ON(!ibm->acpi);
4617 acpi_remove_notify_handler(*ibm->acpi->handle,
4618 ibm->acpi->type,
4619 dispatch_acpi_notify);
4620 ibm->flags.acpi_notify_installed = 0;
4621 ibm->flags.acpi_notify_installed = 0;
4622 }
4623
4624 if (ibm->flags.proc_created) {
4625 dbg_printk(TPACPI_DBG_EXIT,
4626 "%s: remove_proc_entry\n", ibm->name);
4627 remove_proc_entry(ibm->name, proc_dir);
4628 ibm->flags.proc_created = 0;
4629 }
4630
4631 if (ibm->flags.acpi_driver_registered) {
4632 dbg_printk(TPACPI_DBG_EXIT,
4633 "%s: acpi_bus_unregister_driver\n", ibm->name);
4634 BUG_ON(!ibm->acpi);
4635 acpi_bus_unregister_driver(ibm->acpi->driver);
4636 kfree(ibm->acpi->driver);
4637 ibm->acpi->driver = NULL;
4638 ibm->flags.acpi_driver_registered = 0;
4639 }
4640
4641 if (ibm->flags.init_called && ibm->exit) {
4642 ibm->exit();
4643 ibm->flags.init_called = 0;
4644 }
4645
4646 dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name);
4647}
4648
4649
4650
4651static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
4652{
4653 const struct dmi_device *dev = NULL;
4654 char ec_fw_string[18];
4655
4656 if (!tp)
4657 return;
4658
4659 memset(tp, 0, sizeof(*tp));
4660
4661 if (dmi_name_in_vendors("IBM"))
4662 tp->vendor = PCI_VENDOR_ID_IBM;
4663 else if (dmi_name_in_vendors("LENOVO"))
4664 tp->vendor = PCI_VENDOR_ID_LENOVO;
4665 else
4666 return;
4667
4668 tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION),
4669 GFP_KERNEL);
4670 if (!tp->bios_version_str)
4671 return;
4672 tp->bios_model = tp->bios_version_str[0]
4673 | (tp->bios_version_str[1] << 8);
4674
4675
4676
4677
4678
4679
4680
4681
4682 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
4683 if (sscanf(dev->name,
4684 "IBM ThinkPad Embedded Controller -[%17c",
4685 ec_fw_string) == 1) {
4686 ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
4687 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
4688
4689 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
4690 tp->ec_model = ec_fw_string[0]
4691 | (ec_fw_string[1] << 8);
4692 break;
4693 }
4694 }
4695
4696 tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION),
4697 GFP_KERNEL);
4698 if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
4699 kfree(tp->model_str);
4700 tp->model_str = NULL;
4701 }
4702}
4703
4704static int __init probe_for_thinkpad(void)
4705{
4706 int is_thinkpad;
4707
4708 if (acpi_disabled)
4709 return -ENODEV;
4710
4711
4712
4713
4714
4715 is_thinkpad = (thinkpad_id.model_str != NULL);
4716
4717
4718 IBM_ACPIHANDLE_INIT(ec);
4719 if (!ec_handle) {
4720 if (is_thinkpad)
4721 printk(IBM_ERR
4722 "Not yet supported ThinkPad detected!\n");
4723 return -ENODEV;
4724 }
4725
4726
4727
4728
4729
4730 if (!is_thinkpad)
4731 is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM);
4732
4733 if (!is_thinkpad && !force_load)
4734 return -ENODEV;
4735
4736 return 0;
4737}
4738
4739
4740
4741
4742static struct ibm_init_struct ibms_init[] __initdata = {
4743 {
4744 .init = thinkpad_acpi_driver_init,
4745 .data = &thinkpad_acpi_driver_data,
4746 },
4747 {
4748 .init = hotkey_init,
4749 .data = &hotkey_driver_data,
4750 },
4751 {
4752 .init = bluetooth_init,
4753 .data = &bluetooth_driver_data,
4754 },
4755 {
4756 .init = wan_init,
4757 .data = &wan_driver_data,
4758 },
4759 {
4760 .init = video_init,
4761 .data = &video_driver_data,
4762 },
4763 {
4764 .init = light_init,
4765 .data = &light_driver_data,
4766 },
4767#ifdef CONFIG_THINKPAD_ACPI_DOCK
4768 {
4769 .init = dock_init,
4770 .data = &dock_driver_data[0],
4771 },
4772 {
4773 .init = dock_init2,
4774 .data = &dock_driver_data[1],
4775 },
4776#endif
4777#ifdef CONFIG_THINKPAD_ACPI_BAY
4778 {
4779 .init = bay_init,
4780 .data = &bay_driver_data,
4781 },
4782#endif
4783 {
4784 .init = cmos_init,
4785 .data = &cmos_driver_data,
4786 },
4787 {
4788 .init = led_init,
4789 .data = &led_driver_data,
4790 },
4791 {
4792 .init = beep_init,
4793 .data = &beep_driver_data,
4794 },
4795 {
4796 .init = thermal_init,
4797 .data = &thermal_driver_data,
4798 },
4799 {
4800 .data = &ecdump_driver_data,
4801 },
4802 {
4803 .init = brightness_init,
4804 .data = &brightness_driver_data,
4805 },
4806 {
4807 .data = &volume_driver_data,
4808 },
4809 {
4810 .init = fan_init,
4811 .data = &fan_driver_data,
4812 },
4813};
4814
4815static int __init set_ibm_param(const char *val, struct kernel_param *kp)
4816{
4817 unsigned int i;
4818 struct ibm_struct *ibm;
4819
4820 if (!kp || !kp->name || !val)
4821 return -EINVAL;
4822
4823 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
4824 ibm = ibms_init[i].data;
4825 WARN_ON(ibm == NULL);
4826
4827 if (!ibm || !ibm->name)
4828 continue;
4829
4830 if (strcmp(ibm->name, kp->name) == 0 && ibm->write) {
4831 if (strlen(val) > sizeof(ibms_init[i].param) - 2)
4832 return -ENOSPC;
4833 strcpy(ibms_init[i].param, val);
4834 strcat(ibms_init[i].param, ",");
4835 return 0;
4836 }
4837 }
4838
4839 return -EINVAL;
4840}
4841
4842static int experimental;
4843module_param(experimental, int, 0);
4844
4845static u32 dbg_level;
4846module_param_named(debug, dbg_level, uint, 0);
4847
4848static int force_load;
4849module_param(force_load, bool, 0);
4850
4851static int fan_control_allowed;
4852module_param_named(fan_control, fan_control_allowed, bool, 0);
4853
4854static int brightness_mode;
4855module_param_named(brightness_mode, brightness_mode, int, 0);
4856
4857static unsigned int brightness_enable = 2;
4858module_param(brightness_enable, uint, 0);
4859
4860static unsigned int hotkey_report_mode;
4861module_param(hotkey_report_mode, uint, 0);
4862
4863#define IBM_PARAM(feature) \
4864 module_param_call(feature, set_ibm_param, NULL, NULL, 0)
4865
4866IBM_PARAM(hotkey);
4867IBM_PARAM(bluetooth);
4868IBM_PARAM(video);
4869IBM_PARAM(light);
4870#ifdef CONFIG_THINKPAD_ACPI_DOCK
4871IBM_PARAM(dock);
4872#endif
4873#ifdef CONFIG_THINKPAD_ACPI_BAY
4874IBM_PARAM(bay);
4875#endif
4876IBM_PARAM(cmos);
4877IBM_PARAM(led);
4878IBM_PARAM(beep);
4879IBM_PARAM(ecdump);
4880IBM_PARAM(brightness);
4881IBM_PARAM(volume);
4882IBM_PARAM(fan);
4883
4884static int __init thinkpad_acpi_module_init(void)
4885{
4886 int ret, i;
4887
4888 tpacpi_lifecycle = TPACPI_LIFE_INIT;
4889
4890
4891 if (hotkey_report_mode > 2)
4892 return -EINVAL;
4893
4894
4895
4896 get_thinkpad_model_data(&thinkpad_id);
4897 ret = probe_for_thinkpad();
4898 if (ret) {
4899 thinkpad_acpi_module_exit();
4900 return ret;
4901 }
4902
4903
4904
4905 IBM_ACPIHANDLE_INIT(ecrd);
4906 IBM_ACPIHANDLE_INIT(ecwr);
4907
4908 proc_dir = proc_mkdir(IBM_PROC_DIR, acpi_root_dir);
4909 if (!proc_dir) {
4910 printk(IBM_ERR "unable to create proc dir " IBM_PROC_DIR);
4911 thinkpad_acpi_module_exit();
4912 return -ENODEV;
4913 }
4914 proc_dir->owner = THIS_MODULE;
4915
4916 ret = platform_driver_register(&tpacpi_pdriver);
4917 if (ret) {
4918 printk(IBM_ERR "unable to register main platform driver\n");
4919 thinkpad_acpi_module_exit();
4920 return ret;
4921 }
4922 tp_features.platform_drv_registered = 1;
4923
4924 ret = platform_driver_register(&tpacpi_hwmon_pdriver);
4925 if (ret) {
4926 printk(IBM_ERR "unable to register hwmon platform driver\n");
4927 thinkpad_acpi_module_exit();
4928 return ret;
4929 }
4930 tp_features.sensors_pdrv_registered = 1;
4931
4932 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
4933 if (!ret) {
4934 tp_features.platform_drv_attrs_registered = 1;
4935 ret = tpacpi_create_driver_attributes(&tpacpi_hwmon_pdriver.driver);
4936 }
4937 if (ret) {
4938 printk(IBM_ERR "unable to create sysfs driver attributes\n");
4939 thinkpad_acpi_module_exit();
4940 return ret;
4941 }
4942 tp_features.sensors_pdrv_attrs_registered = 1;
4943
4944
4945
4946 tpacpi_pdev = platform_device_register_simple(IBM_DRVR_NAME, -1,
4947 NULL, 0);
4948 if (IS_ERR(tpacpi_pdev)) {
4949 ret = PTR_ERR(tpacpi_pdev);
4950 tpacpi_pdev = NULL;
4951 printk(IBM_ERR "unable to register platform device\n");
4952 thinkpad_acpi_module_exit();
4953 return ret;
4954 }
4955 tpacpi_sensors_pdev = platform_device_register_simple(
4956 IBM_HWMON_DRVR_NAME,
4957 -1, NULL, 0);
4958 if (IS_ERR(tpacpi_sensors_pdev)) {
4959 ret = PTR_ERR(tpacpi_sensors_pdev);
4960 tpacpi_sensors_pdev = NULL;
4961 printk(IBM_ERR "unable to register hwmon platform device\n");
4962 thinkpad_acpi_module_exit();
4963 return ret;
4964 }
4965 ret = device_create_file(&tpacpi_sensors_pdev->dev,
4966 &dev_attr_thinkpad_acpi_pdev_name);
4967 if (ret) {
4968 printk(IBM_ERR
4969 "unable to create sysfs hwmon device attributes\n");
4970 thinkpad_acpi_module_exit();
4971 return ret;
4972 }
4973 tp_features.sensors_pdev_attrs_registered = 1;
4974 tpacpi_hwmon = hwmon_device_register(&tpacpi_sensors_pdev->dev);
4975 if (IS_ERR(tpacpi_hwmon)) {
4976 ret = PTR_ERR(tpacpi_hwmon);
4977 tpacpi_hwmon = NULL;
4978 printk(IBM_ERR "unable to register hwmon device\n");
4979 thinkpad_acpi_module_exit();
4980 return ret;
4981 }
4982 mutex_init(&tpacpi_inputdev_send_mutex);
4983 tpacpi_inputdev = input_allocate_device();
4984 if (!tpacpi_inputdev) {
4985 printk(IBM_ERR "unable to allocate input device\n");
4986 thinkpad_acpi_module_exit();
4987 return -ENOMEM;
4988 } else {
4989
4990 tpacpi_inputdev->name = "ThinkPad Extra Buttons";
4991 tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0";
4992 tpacpi_inputdev->id.bustype = BUS_HOST;
4993 tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ?
4994 thinkpad_id.vendor :
4995 PCI_VENDOR_ID_IBM;
4996 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
4997 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
4998 }
4999 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
5000 ret = ibm_init(&ibms_init[i]);
5001 if (ret >= 0 && *ibms_init[i].param)
5002 ret = ibms_init[i].data->write(ibms_init[i].param);
5003 if (ret < 0) {
5004 thinkpad_acpi_module_exit();
5005 return ret;
5006 }
5007 }
5008 ret = input_register_device(tpacpi_inputdev);
5009 if (ret < 0) {
5010 printk(IBM_ERR "unable to register input device\n");
5011 thinkpad_acpi_module_exit();
5012 return ret;
5013 } else {
5014 tp_features.input_device_registered = 1;
5015 }
5016
5017 tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
5018 return 0;
5019}
5020
5021static void thinkpad_acpi_module_exit(void)
5022{
5023 struct ibm_struct *ibm, *itmp;
5024
5025 tpacpi_lifecycle = TPACPI_LIFE_EXITING;
5026
5027 list_for_each_entry_safe_reverse(ibm, itmp,
5028 &tpacpi_all_drivers,
5029 all_drivers) {
5030 ibm_exit(ibm);
5031 }
5032
5033 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
5034
5035 if (tpacpi_inputdev) {
5036 if (tp_features.input_device_registered)
5037 input_unregister_device(tpacpi_inputdev);
5038 else
5039 input_free_device(tpacpi_inputdev);
5040 }
5041
5042 if (tpacpi_hwmon)
5043 hwmon_device_unregister(tpacpi_hwmon);
5044
5045 if (tp_features.sensors_pdev_attrs_registered)
5046 device_remove_file(&tpacpi_sensors_pdev->dev,
5047 &dev_attr_thinkpad_acpi_pdev_name);
5048 if (tpacpi_sensors_pdev)
5049 platform_device_unregister(tpacpi_sensors_pdev);
5050 if (tpacpi_pdev)
5051 platform_device_unregister(tpacpi_pdev);
5052
5053 if (tp_features.sensors_pdrv_attrs_registered)
5054 tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver);
5055 if (tp_features.platform_drv_attrs_registered)
5056 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
5057
5058 if (tp_features.sensors_pdrv_registered)
5059 platform_driver_unregister(&tpacpi_hwmon_pdriver);
5060
5061 if (tp_features.platform_drv_registered)
5062 platform_driver_unregister(&tpacpi_pdriver);
5063
5064 if (proc_dir)
5065 remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
5066
5067 kfree(thinkpad_id.bios_version_str);
5068 kfree(thinkpad_id.ec_version_str);
5069 kfree(thinkpad_id.model_str);
5070}
5071
5072module_init(thinkpad_acpi_module_init);
5073module_exit(thinkpad_acpi_module_exit);
5074