]> err.no Git - linux-2.6/blob - drivers/misc/thinkpad_acpi.c
a56526500c1895d4d689119196634b342de2c047
[linux-2.6] / drivers / misc / thinkpad_acpi.c
1 /*
2  *  thinkpad_acpi.c - ThinkPad ACPI Extras
3  *
4  *
5  *  Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
6  *  Copyright (C) 2006-2007 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  *  02110-1301, USA.
22  */
23
24 #define IBM_VERSION "0.14"
25 #define TPACPI_SYSFS_VERSION 0x000100
26
27 /*
28  *  Changelog:
29  *  2007-03-27  0.14    renamed to thinkpad_acpi and moved to
30  *                      drivers/misc.
31  *
32  *  2006-11-22  0.13    new maintainer
33  *                      changelog now lives in git commit history, and will
34  *                      not be updated further in-file.
35  *
36  *  2005-08-17  0.12    fix compilation on 2.6.13-rc kernels
37  *  2005-03-17  0.11    support for 600e, 770x
38  *                          thanks to Jamie Lentin <lentinj@dial.pipex.com>
39  *                      support for 770e, G41
40  *                      G40 and G41 don't have a thinklight
41  *                      temperatures no longer experimental
42  *                      experimental brightness control
43  *                      experimental volume control
44  *                      experimental fan enable/disable
45  *  2005-01-16  0.10    fix module loading on R30, R31
46  *  2005-01-16  0.9     support for 570, R30, R31
47  *                      ultrabay support on A22p, A3x
48  *                      limit arg for cmos, led, beep, drop experimental status
49  *                      more capable led control on A21e, A22p, T20-22, X20
50  *                      experimental temperatures and fan speed
51  *                      experimental embedded controller register dump
52  *                      mark more functions as __init, drop incorrect __exit
53  *                      use MODULE_VERSION
54  *                          thanks to Henrik Brix Andersen <brix@gentoo.org>
55  *                      fix parameter passing on module loading
56  *                          thanks to Rusty Russell <rusty@rustcorp.com.au>
57  *                          thanks to Jim Radford <radford@blackbean.org>
58  *  2004-11-08  0.8     fix init error case, don't return from a macro
59  *                          thanks to Chris Wright <chrisw@osdl.org>
60  *  2004-10-23  0.7     fix module loading on A21e, A22p, T20, T21, X20
61  *                      fix led control on A21e
62  *  2004-10-19  0.6     use acpi_bus_register_driver() to claim HKEY device
63  *  2004-10-18  0.5     thinklight support on A21e, G40, R32, T20, T21, X20
64  *                      proc file format changed
65  *                      video_switch command
66  *                      experimental cmos control
67  *                      experimental led control
68  *                      experimental acpi sounds
69  *  2004-09-16  0.4     support for module parameters
70  *                      hotkey mask can be prefixed by 0x
71  *                      video output switching
72  *                      video expansion control
73  *                      ultrabay eject support
74  *                      removed lcd brightness/on/off control, didn't work
75  *  2004-08-17  0.3     support for R40
76  *                      lcd off, brightness control
77  *                      thinklight on/off
78  *  2004-08-14  0.2     support for T series, X20
79  *                      bluetooth enable/disable
80  *                      hotkey events disabled by default
81  *                      removed fan control, currently useless
82  *  2004-08-09  0.1     initial release, support for X series
83  */
84
85 #include "thinkpad_acpi.h"
86
87 MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
88 MODULE_DESCRIPTION(IBM_DESC);
89 MODULE_VERSION(IBM_VERSION);
90 MODULE_LICENSE("GPL");
91
92 /* Please remove this in year 2009 */
93 MODULE_ALIAS("ibm_acpi");
94
95 #define __unused __attribute__ ((unused))
96
97 /****************************************************************************
98  ****************************************************************************
99  *
100  * ACPI Helpers and device model
101  *
102  ****************************************************************************
103  ****************************************************************************/
104
105 /*************************************************************************
106  * ACPI basic handles
107  */
108
109 static acpi_handle root_handle = NULL;
110
111 #define IBM_HANDLE(object, parent, paths...)                    \
112         static acpi_handle  object##_handle;                    \
113         static acpi_handle *object##_parent = &parent##_handle; \
114         static char        *object##_path;                      \
115         static char        *object##_paths[] = { paths }
116
117 IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",      /* 240, 240x */
118            "\\_SB.PCI.ISA.EC",  /* 570 */
119            "\\_SB.PCI0.ISA0.EC0",       /* 600e/x, 770e, 770x */
120            "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */
121            "\\_SB.PCI0.AD4S.EC0",       /* i1400, R30 */
122            "\\_SB.PCI0.ICH3.EC0",       /* R31 */
123            "\\_SB.PCI0.LPC.EC", /* all others */
124            );
125
126 IBM_HANDLE(ecrd, ec, "ECRD");   /* 570 */
127 IBM_HANDLE(ecwr, ec, "ECWR");   /* 570 */
128
129
130 /*************************************************************************
131  * Misc ACPI handles
132  */
133
134 IBM_HANDLE(cmos, root, "\\UCMS",        /* R50, R50e, R50p, R51, T4x, X31, X40 */
135            "\\CMOS",            /* A3x, G4x, R32, T23, T30, X22-24, X30 */
136            "\\CMS",             /* R40, R40e */
137            );                   /* all others */
138
139 IBM_HANDLE(hkey, ec, "\\_SB.HKEY",      /* 600e/x, 770e, 770x */
140            "^HKEY",             /* R30, R31 */
141            "HKEY",              /* all others */
142            );                   /* 570 */
143
144
145 /*************************************************************************
146  * ACPI helpers
147  */
148
149 static int acpi_evalf(acpi_handle handle,
150                       void *res, char *method, char *fmt, ...)
151 {
152         char *fmt0 = fmt;
153         struct acpi_object_list params;
154         union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
155         struct acpi_buffer result, *resultp;
156         union acpi_object out_obj;
157         acpi_status status;
158         va_list ap;
159         char res_type;
160         int success;
161         int quiet;
162
163         if (!*fmt) {
164                 printk(IBM_ERR "acpi_evalf() called with empty format\n");
165                 return 0;
166         }
167
168         if (*fmt == 'q') {
169                 quiet = 1;
170                 fmt++;
171         } else
172                 quiet = 0;
173
174         res_type = *(fmt++);
175
176         params.count = 0;
177         params.pointer = &in_objs[0];
178
179         va_start(ap, fmt);
180         while (*fmt) {
181                 char c = *(fmt++);
182                 switch (c) {
183                 case 'd':       /* int */
184                         in_objs[params.count].integer.value = va_arg(ap, int);
185                         in_objs[params.count++].type = ACPI_TYPE_INTEGER;
186                         break;
187                         /* add more types as needed */
188                 default:
189                         printk(IBM_ERR "acpi_evalf() called "
190                                "with invalid format character '%c'\n", c);
191                         return 0;
192                 }
193         }
194         va_end(ap);
195
196         if (res_type != 'v') {
197                 result.length = sizeof(out_obj);
198                 result.pointer = &out_obj;
199                 resultp = &result;
200         } else
201                 resultp = NULL;
202
203         status = acpi_evaluate_object(handle, method, &params, resultp);
204
205         switch (res_type) {
206         case 'd':               /* int */
207                 if (res)
208                         *(int *)res = out_obj.integer.value;
209                 success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
210                 break;
211         case 'v':               /* void */
212                 success = status == AE_OK;
213                 break;
214                 /* add more types as needed */
215         default:
216                 printk(IBM_ERR "acpi_evalf() called "
217                        "with invalid format character '%c'\n", res_type);
218                 return 0;
219         }
220
221         if (!success && !quiet)
222                 printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
223                        method, fmt0, status);
224
225         return success;
226 }
227
228 static void __unused acpi_print_int(acpi_handle handle, char *method)
229 {
230         int i;
231
232         if (acpi_evalf(handle, &i, method, "d"))
233                 printk(IBM_INFO "%s = 0x%x\n", method, i);
234         else
235                 printk(IBM_ERR "error calling %s\n", method);
236 }
237
238 static int acpi_ec_read(int i, u8 * p)
239 {
240         int v;
241
242         if (ecrd_handle) {
243                 if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
244                         return 0;
245                 *p = v;
246         } else {
247                 if (ec_read(i, p) < 0)
248                         return 0;
249         }
250
251         return 1;
252 }
253
254 static int acpi_ec_write(int i, u8 v)
255 {
256         if (ecwr_handle) {
257                 if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
258                         return 0;
259         } else {
260                 if (ec_write(i, v) < 0)
261                         return 0;
262         }
263
264         return 1;
265 }
266
267 static int _sta(acpi_handle handle)
268 {
269         int status;
270
271         if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
272                 status = 0;
273
274         return status;
275 }
276
277 static int issue_thinkpad_cmos_command(int cmos_cmd)
278 {
279         if (!cmos_handle)
280                 return -ENXIO;
281
282         if (!acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd))
283                 return -EIO;
284
285         return 0;
286 }
287
288 /*************************************************************************
289  * ACPI device model
290  */
291
292 static void drv_acpi_handle_init(char *name,
293                            acpi_handle *handle, acpi_handle parent,
294                            char **paths, int num_paths, char **path)
295 {
296         int i;
297         acpi_status status;
298
299         vdbg_printk(TPACPI_DBG_INIT, "trying to locate ACPI handle for %s\n",
300                 name);
301
302         for (i = 0; i < num_paths; i++) {
303                 status = acpi_get_handle(parent, paths[i], handle);
304                 if (ACPI_SUCCESS(status)) {
305                         *path = paths[i];
306                         dbg_printk(TPACPI_DBG_INIT,
307                                    "Found ACPI handle %s for %s\n",
308                                    *path, name);
309                         return;
310                 }
311         }
312
313         vdbg_printk(TPACPI_DBG_INIT, "ACPI handle for %s not found\n",
314                     name);
315         *handle = NULL;
316 }
317
318 static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data)
319 {
320         struct ibm_struct *ibm = data;
321
322         if (!ibm || !ibm->acpi || !ibm->acpi->notify)
323                 return;
324
325         ibm->acpi->notify(ibm, event);
326 }
327
328 static int __init setup_acpi_notify(struct ibm_struct *ibm)
329 {
330         acpi_status status;
331         int rc;
332
333         BUG_ON(!ibm->acpi);
334
335         if (!*ibm->acpi->handle)
336                 return 0;
337
338         vdbg_printk(TPACPI_DBG_INIT,
339                 "setting up ACPI notify for %s\n", ibm->name);
340
341         rc = acpi_bus_get_device(*ibm->acpi->handle, &ibm->acpi->device);
342         if (rc < 0) {
343                 printk(IBM_ERR "acpi_bus_get_device(%s) failed: %d\n",
344                         ibm->name, rc);
345                 return -ENODEV;
346         }
347
348         acpi_driver_data(ibm->acpi->device) = ibm;
349         sprintf(acpi_device_class(ibm->acpi->device), "%s/%s",
350                 IBM_ACPI_EVENT_PREFIX,
351                 ibm->name);
352
353         status = acpi_install_notify_handler(*ibm->acpi->handle,
354                         ibm->acpi->type, dispatch_acpi_notify, ibm);
355         if (ACPI_FAILURE(status)) {
356                 if (status == AE_ALREADY_EXISTS) {
357                         printk(IBM_NOTICE "another device driver is already handling %s events\n",
358                                 ibm->name);
359                 } else {
360                         printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
361                                 ibm->name, status);
362                 }
363                 return -ENODEV;
364         }
365         ibm->flags.acpi_notify_installed = 1;
366         return 0;
367 }
368
369 static int __init tpacpi_device_add(struct acpi_device *device)
370 {
371         return 0;
372 }
373
374 static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
375 {
376         int rc;
377
378         dbg_printk(TPACPI_DBG_INIT,
379                 "registering %s as an ACPI driver\n", ibm->name);
380
381         BUG_ON(!ibm->acpi);
382
383         ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
384         if (!ibm->acpi->driver) {
385                 printk(IBM_ERR "kzalloc(ibm->driver) failed\n");
386                 return -ENOMEM;
387         }
388
389         sprintf(ibm->acpi->driver->name, "%s_%s", IBM_NAME, ibm->name);
390         ibm->acpi->driver->ids = ibm->acpi->hid;
391         ibm->acpi->driver->ops.add = &tpacpi_device_add;
392
393         rc = acpi_bus_register_driver(ibm->acpi->driver);
394         if (rc < 0) {
395                 printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
396                        ibm->acpi->hid, rc);
397                 kfree(ibm->acpi->driver);
398                 ibm->acpi->driver = NULL;
399         } else if (!rc)
400                 ibm->flags.acpi_driver_registered = 1;
401
402         return rc;
403 }
404
405
406 /****************************************************************************
407  ****************************************************************************
408  *
409  * Procfs Helpers
410  *
411  ****************************************************************************
412  ****************************************************************************/
413
414 static int dispatch_procfs_read(char *page, char **start, off_t off,
415                         int count, int *eof, void *data)
416 {
417         struct ibm_struct *ibm = data;
418         int len;
419
420         if (!ibm || !ibm->read)
421                 return -EINVAL;
422
423         len = ibm->read(page);
424         if (len < 0)
425                 return len;
426
427         if (len <= off + count)
428                 *eof = 1;
429         *start = page + off;
430         len -= off;
431         if (len > count)
432                 len = count;
433         if (len < 0)
434                 len = 0;
435
436         return len;
437 }
438
439 static int dispatch_procfs_write(struct file *file,
440                         const char __user * userbuf,
441                         unsigned long count, void *data)
442 {
443         struct ibm_struct *ibm = data;
444         char *kernbuf;
445         int ret;
446
447         if (!ibm || !ibm->write)
448                 return -EINVAL;
449
450         kernbuf = kmalloc(count + 2, GFP_KERNEL);
451         if (!kernbuf)
452                 return -ENOMEM;
453
454         if (copy_from_user(kernbuf, userbuf, count)) {
455                 kfree(kernbuf);
456                 return -EFAULT;
457         }
458
459         kernbuf[count] = 0;
460         strcat(kernbuf, ",");
461         ret = ibm->write(kernbuf);
462         if (ret == 0)
463                 ret = count;
464
465         kfree(kernbuf);
466
467         return ret;
468 }
469
470 static char *next_cmd(char **cmds)
471 {
472         char *start = *cmds;
473         char *end;
474
475         while ((end = strchr(start, ',')) && end == start)
476                 start = end + 1;
477
478         if (!end)
479                 return NULL;
480
481         *end = 0;
482         *cmds = end + 1;
483         return start;
484 }
485
486
487 /****************************************************************************
488  ****************************************************************************
489  *
490  * Device model: hwmon and platform
491  *
492  ****************************************************************************
493  ****************************************************************************/
494
495 static struct platform_device *tpacpi_pdev = NULL;
496 static struct class_device *tpacpi_hwmon = NULL;
497
498 static struct platform_driver tpacpi_pdriver = {
499         .driver = {
500                 .name = IBM_DRVR_NAME,
501                 .owner = THIS_MODULE,
502         },
503 };
504
505
506 /*************************************************************************
507  * thinkpad-acpi driver attributes
508  */
509
510 /* interface_version --------------------------------------------------- */
511 static ssize_t tpacpi_driver_interface_version_show(
512                                 struct device_driver *drv,
513                                 char *buf)
514 {
515         return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION);
516 }
517
518 static DRIVER_ATTR(interface_version, S_IRUGO,
519                 tpacpi_driver_interface_version_show, NULL);
520
521 /* debug_level --------------------------------------------------------- */
522 static ssize_t tpacpi_driver_debug_show(struct device_driver *drv,
523                                                 char *buf)
524 {
525         return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level);
526 }
527
528 static ssize_t tpacpi_driver_debug_store(struct device_driver *drv,
529                                                 const char *buf, size_t count)
530 {
531         unsigned long t;
532
533         if (parse_strtoul(buf, 0xffff, &t))
534                 return -EINVAL;
535
536         dbg_level = t;
537
538         return count;
539 }
540
541 static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
542                 tpacpi_driver_debug_show, tpacpi_driver_debug_store);
543
544 /* version ------------------------------------------------------------- */
545 static ssize_t tpacpi_driver_version_show(struct device_driver *drv,
546                                                 char *buf)
547 {
548         return snprintf(buf, PAGE_SIZE, "%s v%s\n", IBM_DESC, IBM_VERSION);
549 }
550
551 static DRIVER_ATTR(version, S_IRUGO,
552                 tpacpi_driver_version_show, NULL);
553
554 /* --------------------------------------------------------------------- */
555
556 static struct driver_attribute* tpacpi_driver_attributes[] = {
557         &driver_attr_debug_level, &driver_attr_version,
558         &driver_attr_interface_version,
559 };
560
561 static int __init tpacpi_create_driver_attributes(struct device_driver *drv)
562 {
563         int i, res;
564
565         i = 0;
566         res = 0;
567         while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) {
568                 res = driver_create_file(drv, tpacpi_driver_attributes[i]);
569                 i++;
570         }
571
572         return res;
573 }
574
575 static void tpacpi_remove_driver_attributes(struct device_driver *drv)
576 {
577         int i;
578
579         for(i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
580                 driver_remove_file(drv, tpacpi_driver_attributes[i]);
581 }
582
583 /*************************************************************************
584  * sysfs support helpers
585  */
586
587 struct attribute_set_obj {
588         struct attribute_set s;
589         struct attribute *a;
590 } __attribute__((packed));
591
592 static struct attribute_set *create_attr_set(unsigned int max_members,
593                                                 const char* name)
594 {
595         struct attribute_set_obj *sobj;
596
597         if (max_members == 0)
598                 return NULL;
599
600         /* Allocates space for implicit NULL at the end too */
601         sobj = kzalloc(sizeof(struct attribute_set_obj) +
602                     max_members * sizeof(struct attribute *),
603                     GFP_KERNEL);
604         if (!sobj)
605                 return NULL;
606         sobj->s.max_members = max_members;
607         sobj->s.group.attrs = &sobj->a;
608         sobj->s.group.name = name;
609
610         return &sobj->s;
611 }
612
613 /* not multi-threaded safe, use it in a single thread per set */
614 static int add_to_attr_set(struct attribute_set* s, struct attribute *attr)
615 {
616         if (!s || !attr)
617                 return -EINVAL;
618
619         if (s->members >= s->max_members)
620                 return -ENOMEM;
621
622         s->group.attrs[s->members] = attr;
623         s->members++;
624
625         return 0;
626 }
627
628 static int add_many_to_attr_set(struct attribute_set* s,
629                         struct attribute **attr,
630                         unsigned int count)
631 {
632         int i, res;
633
634         for (i = 0; i < count; i++) {
635                 res = add_to_attr_set(s, attr[i]);
636                 if (res)
637                         return res;
638         }
639
640         return 0;
641 }
642
643 static void delete_attr_set(struct attribute_set* s, struct kobject *kobj)
644 {
645         sysfs_remove_group(kobj, &s->group);
646         destroy_attr_set(s);
647 }
648
649 static int parse_strtoul(const char *buf,
650                 unsigned long max, unsigned long *value)
651 {
652         char *endp;
653
654         *value = simple_strtoul(buf, &endp, 0);
655         while (*endp && isspace(*endp))
656                 endp++;
657         if (*endp || *value > max)
658                 return -EINVAL;
659
660         return 0;
661 }
662
663 /****************************************************************************
664  ****************************************************************************
665  *
666  * Subdrivers
667  *
668  ****************************************************************************
669  ****************************************************************************/
670
671 /*************************************************************************
672  * thinkpad-acpi init subdriver
673  */
674
675 static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
676 {
677         printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
678         printk(IBM_INFO "%s\n", IBM_URL);
679
680         if (ibm_thinkpad_ec_found)
681                 printk(IBM_INFO "ThinkPad EC firmware %s\n",
682                        ibm_thinkpad_ec_found);
683
684         return 0;
685 }
686
687 static int thinkpad_acpi_driver_read(char *p)
688 {
689         int len = 0;
690
691         len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC);
692         len += sprintf(p + len, "version:\t%s\n", IBM_VERSION);
693
694         return len;
695 }
696
697 static struct ibm_struct thinkpad_acpi_driver_data = {
698         .name = "driver",
699         .read = thinkpad_acpi_driver_read,
700 };
701
702 /*************************************************************************
703  * Hotkey subdriver
704  */
705
706 static int hotkey_orig_status;
707 static int hotkey_orig_mask;
708
709 static int __init hotkey_init(struct ibm_init_struct *iibm)
710 {
711         int res;
712
713         vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
714
715         IBM_ACPIHANDLE_INIT(hkey);
716         mutex_init(&hotkey_mutex);
717
718         /* hotkey not supported on 570 */
719         tp_features.hotkey = hkey_handle != NULL;
720
721         vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n",
722                 str_supported(tp_features.hotkey));
723
724         if (tp_features.hotkey) {
725                 /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
726                    A30, R30, R31, T20-22, X20-21, X22-24 */
727                 tp_features.hotkey_mask =
728                         acpi_evalf(hkey_handle, NULL, "DHKN", "qv");
729
730                 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
731                         str_supported(tp_features.hotkey_mask));
732
733                 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
734                 if (res)
735                         return res;
736         }
737
738         return (tp_features.hotkey)? 0 : 1;
739 }
740
741 static void hotkey_exit(void)
742 {
743         int res;
744
745         if (tp_features.hotkey) {
746                 dbg_printk(TPACPI_DBG_EXIT, "restoring original hotkey mask\n");
747                 res = hotkey_set(hotkey_orig_status, hotkey_orig_mask);
748                 if (res)
749                         printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n");
750         }
751 }
752
753 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
754 {
755         int hkey;
756
757         if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d"))
758                 acpi_bus_generate_event(ibm->acpi->device, event, hkey);
759         else {
760                 printk(IBM_ERR "unknown hotkey event %d\n", event);
761                 acpi_bus_generate_event(ibm->acpi->device, event, 0);
762         }
763 }
764
765 /*
766  * Call with hotkey_mutex held
767  */
768 static int hotkey_get(int *status, int *mask)
769 {
770         if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
771                 return -EIO;
772
773         if (tp_features.hotkey_mask)
774                 if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
775                         return -EIO;
776
777         return 0;
778 }
779
780 /*
781  * Call with hotkey_mutex held
782  */
783 static int hotkey_set(int status, int mask)
784 {
785         int i;
786
787         if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
788                 return -EIO;
789
790         if (tp_features.hotkey_mask)
791                 for (i = 0; i < 32; i++) {
792                         int bit = ((1 << i) & mask) != 0;
793                         if (!acpi_evalf(hkey_handle,
794                                         NULL, "MHKM", "vdd", i + 1, bit))
795                                 return -EIO;
796                 }
797
798         return 0;
799 }
800
801 static int hotkey_read(char *p)
802 {
803         int res, status, mask;
804         int len = 0;
805
806         if (!tp_features.hotkey) {
807                 len += sprintf(p + len, "status:\t\tnot supported\n");
808                 return len;
809         }
810
811         res = mutex_lock_interruptible(&hotkey_mutex);
812         if (res < 0)
813                 return res;
814         res = hotkey_get(&status, &mask);
815         mutex_unlock(&hotkey_mutex);
816         if (res)
817                 return res;
818
819         len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
820         if (tp_features.hotkey_mask) {
821                 len += sprintf(p + len, "mask:\t\t0x%04x\n", mask);
822                 len += sprintf(p + len,
823                                "commands:\tenable, disable, reset, <mask>\n");
824         } else {
825                 len += sprintf(p + len, "mask:\t\tnot supported\n");
826                 len += sprintf(p + len, "commands:\tenable, disable, reset\n");
827         }
828
829         return len;
830 }
831
832 static int hotkey_write(char *buf)
833 {
834         int res, status, mask;
835         char *cmd;
836         int do_cmd = 0;
837
838         if (!tp_features.hotkey)
839                 return -ENODEV;
840
841         res = mutex_lock_interruptible(&hotkey_mutex);
842         if (res < 0)
843                 return res;
844
845         res = hotkey_get(&status, &mask);
846         if (res)
847                 goto errexit;
848
849         res = 0;
850         while ((cmd = next_cmd(&buf))) {
851                 if (strlencmp(cmd, "enable") == 0) {
852                         status = 1;
853                 } else if (strlencmp(cmd, "disable") == 0) {
854                         status = 0;
855                 } else if (strlencmp(cmd, "reset") == 0) {
856                         status = hotkey_orig_status;
857                         mask = hotkey_orig_mask;
858                 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
859                         /* mask set */
860                 } else if (sscanf(cmd, "%x", &mask) == 1) {
861                         /* mask set */
862                 } else {
863                         res = -EINVAL;
864                         goto errexit;
865                 }
866                 do_cmd = 1;
867         }
868
869         if (do_cmd)
870                 res = hotkey_set(status, mask);
871
872 errexit:
873         mutex_unlock(&hotkey_mutex);
874         return res;
875 }
876
877 static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = {
878         .hid = IBM_HKEY_HID,
879         .notify = hotkey_notify,
880         .handle = &hkey_handle,
881         .type = ACPI_DEVICE_NOTIFY,
882 };
883
884 static struct ibm_struct hotkey_driver_data = {
885         .name = "hotkey",
886         .read = hotkey_read,
887         .write = hotkey_write,
888         .exit = hotkey_exit,
889         .acpi = &ibm_hotkey_acpidriver,
890 };
891
892 /*************************************************************************
893  * Bluetooth subdriver
894  */
895
896 static int __init bluetooth_init(struct ibm_init_struct *iibm)
897 {
898         int status = 0;
899
900         vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n");
901
902         IBM_ACPIHANDLE_INIT(hkey);
903
904         /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
905            G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
906         tp_features.bluetooth = hkey_handle &&
907             acpi_evalf(hkey_handle, &status, "GBDC", "qd");
908
909         vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s, status 0x%02x\n",
910                 str_supported(tp_features.bluetooth),
911                 status);
912
913         if (tp_features.bluetooth &&
914             !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
915                 /* no bluetooth hardware present in system */
916                 tp_features.bluetooth = 0;
917                 dbg_printk(TPACPI_DBG_INIT,
918                            "bluetooth hardware not installed\n");
919         }
920
921         return (tp_features.bluetooth)? 0 : 1;
922 }
923
924 static int bluetooth_get_radiosw(void)
925 {
926         int status;
927
928         if (!tp_features.bluetooth)
929                 return -ENODEV;
930
931         if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
932                 return -EIO;
933
934         return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0);
935 }
936
937 static int bluetooth_set_radiosw(int radio_on)
938 {
939         int status;
940
941         if (!tp_features.bluetooth)
942                 return -ENODEV;
943
944         if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
945                 return -EIO;
946         if (radio_on)
947                 status |= TP_ACPI_BLUETOOTH_RADIOSSW;
948         else
949                 status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
950         if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
951                 return -EIO;
952
953         return 0;
954 }
955
956 static int bluetooth_read(char *p)
957 {
958         int len = 0;
959         int status = bluetooth_get_radiosw();
960
961         if (!tp_features.bluetooth)
962                 len += sprintf(p + len, "status:\t\tnot supported\n");
963         else {
964                 len += sprintf(p + len, "status:\t\t%s\n",
965                                 (status)? "enabled" : "disabled");
966                 len += sprintf(p + len, "commands:\tenable, disable\n");
967         }
968
969         return len;
970 }
971
972 static int bluetooth_write(char *buf)
973 {
974         char *cmd;
975
976         if (!tp_features.bluetooth)
977                 return -ENODEV;
978
979         while ((cmd = next_cmd(&buf))) {
980                 if (strlencmp(cmd, "enable") == 0) {
981                         bluetooth_set_radiosw(1);
982                 } else if (strlencmp(cmd, "disable") == 0) {
983                         bluetooth_set_radiosw(0);
984                 } else
985                         return -EINVAL;
986         }
987
988         return 0;
989 }
990
991 static struct ibm_struct bluetooth_driver_data = {
992         .name = "bluetooth",
993         .read = bluetooth_read,
994         .write = bluetooth_write,
995 };
996
997 /*************************************************************************
998  * Wan subdriver
999  */
1000
1001 static int __init wan_init(struct ibm_init_struct *iibm)
1002 {
1003         int status = 0;
1004
1005         vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n");
1006
1007         IBM_ACPIHANDLE_INIT(hkey);
1008
1009         tp_features.wan = hkey_handle &&
1010             acpi_evalf(hkey_handle, &status, "GWAN", "qd");
1011
1012         vdbg_printk(TPACPI_DBG_INIT, "wan is %s, status 0x%02x\n",
1013                 str_supported(tp_features.wan),
1014                 status);
1015
1016         if (tp_features.wan &&
1017             !(status & TP_ACPI_WANCARD_HWPRESENT)) {
1018                 /* no wan hardware present in system */
1019                 tp_features.wan = 0;
1020                 dbg_printk(TPACPI_DBG_INIT,
1021                            "wan hardware not installed\n");
1022         }
1023
1024         return (tp_features.wan)? 0 : 1;
1025 }
1026
1027 static int wan_get_radiosw(void)
1028 {
1029         int status;
1030
1031         if (!tp_features.wan)
1032                 return -ENODEV;
1033
1034         if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
1035                 return -EIO;
1036
1037         return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0);
1038 }
1039
1040 static int wan_set_radiosw(int radio_on)
1041 {
1042         int status;
1043
1044         if (!tp_features.wan)
1045                 return -ENODEV;
1046
1047         if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
1048                 return -EIO;
1049         if (radio_on)
1050                 status |= TP_ACPI_WANCARD_RADIOSSW;
1051         else
1052                 status &= ~TP_ACPI_WANCARD_RADIOSSW;
1053         if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
1054                 return -EIO;
1055
1056         return 0;
1057 }
1058
1059 static int wan_read(char *p)
1060 {
1061         int len = 0;
1062         int status = wan_get_radiosw();
1063
1064         if (!tp_features.wan)
1065                 len += sprintf(p + len, "status:\t\tnot supported\n");
1066         else {
1067                 len += sprintf(p + len, "status:\t\t%s\n",
1068                                 (status)? "enabled" : "disabled");
1069                 len += sprintf(p + len, "commands:\tenable, disable\n");
1070         }
1071
1072         return len;
1073 }
1074
1075 static int wan_write(char *buf)
1076 {
1077         char *cmd;
1078
1079         if (!tp_features.wan)
1080                 return -ENODEV;
1081
1082         while ((cmd = next_cmd(&buf))) {
1083                 if (strlencmp(cmd, "enable") == 0) {
1084                         wan_set_radiosw(1);
1085                 } else if (strlencmp(cmd, "disable") == 0) {
1086                         wan_set_radiosw(0);
1087                 } else
1088                         return -EINVAL;
1089         }
1090
1091         return 0;
1092 }
1093
1094 static struct ibm_struct wan_driver_data = {
1095         .name = "wan",
1096         .read = wan_read,
1097         .write = wan_write,
1098         .flags.experimental = 1,
1099 };
1100
1101 /*************************************************************************
1102  * Video subdriver
1103  */
1104
1105 static enum video_access_mode video_supported;
1106 static int video_orig_autosw;
1107
1108 IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA",      /* 570 */
1109            "\\_SB.PCI0.AGP0.VID0",      /* 600e/x, 770x */
1110            "\\_SB.PCI0.VID0",   /* 770e */
1111            "\\_SB.PCI0.VID",    /* A21e, G4x, R50e, X30, X40 */
1112            "\\_SB.PCI0.AGP.VID",        /* all others */
1113            );                           /* R30, R31 */
1114
1115 IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID");  /* G41 */
1116
1117 static int __init video_init(struct ibm_init_struct *iibm)
1118 {
1119         int ivga;
1120
1121         vdbg_printk(TPACPI_DBG_INIT, "initializing video subdriver\n");
1122
1123         IBM_ACPIHANDLE_INIT(vid);
1124         IBM_ACPIHANDLE_INIT(vid2);
1125
1126         if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
1127                 /* G41, assume IVGA doesn't change */
1128                 vid_handle = vid2_handle;
1129
1130         if (!vid_handle)
1131                 /* video switching not supported on R30, R31 */
1132                 video_supported = TPACPI_VIDEO_NONE;
1133         else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
1134                 /* 570 */
1135                 video_supported = TPACPI_VIDEO_570;
1136         else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
1137                 /* 600e/x, 770e, 770x */
1138                 video_supported = TPACPI_VIDEO_770;
1139         else
1140                 /* all others */
1141                 video_supported = TPACPI_VIDEO_NEW;
1142
1143         vdbg_printk(TPACPI_DBG_INIT, "video is %s, mode %d\n",
1144                 str_supported(video_supported != TPACPI_VIDEO_NONE),
1145                 video_supported);
1146
1147         return (video_supported != TPACPI_VIDEO_NONE)? 0 : 1;
1148 }
1149
1150 static void video_exit(void)
1151 {
1152         dbg_printk(TPACPI_DBG_EXIT,
1153                    "restoring original video autoswitch mode\n");
1154         if (video_autosw_set(video_orig_autosw))
1155                 printk(IBM_ERR "error while trying to restore original "
1156                         "video autoswitch mode\n");
1157 }
1158
1159 static int video_outputsw_get(void)
1160 {
1161         int status = 0;
1162         int i;
1163
1164         switch (video_supported) {
1165         case TPACPI_VIDEO_570:
1166                 if (!acpi_evalf(NULL, &i, "\\_SB.PHS", "dd",
1167                                  TP_ACPI_VIDEO_570_PHSCMD))
1168                         return -EIO;
1169                 status = i & TP_ACPI_VIDEO_570_PHSMASK;
1170                 break;
1171         case TPACPI_VIDEO_770:
1172                 if (!acpi_evalf(NULL, &i, "\\VCDL", "d"))
1173                         return -EIO;
1174                 if (i)
1175                         status |= TP_ACPI_VIDEO_S_LCD;
1176                 if (!acpi_evalf(NULL, &i, "\\VCDC", "d"))
1177                         return -EIO;
1178                 if (i)
1179                         status |= TP_ACPI_VIDEO_S_CRT;
1180                 break;
1181         case TPACPI_VIDEO_NEW:
1182                 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1) ||
1183                     !acpi_evalf(NULL, &i, "\\VCDC", "d"))
1184                         return -EIO;
1185                 if (i)
1186                         status |= TP_ACPI_VIDEO_S_CRT;
1187
1188                 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0) ||
1189                     !acpi_evalf(NULL, &i, "\\VCDL", "d"))
1190                         return -EIO;
1191                 if (i)
1192                         status |= TP_ACPI_VIDEO_S_LCD;
1193                 if (!acpi_evalf(NULL, &i, "\\VCDD", "d"))
1194                         return -EIO;
1195                 if (i)
1196                         status |= TP_ACPI_VIDEO_S_DVI;
1197                 break;
1198         default:
1199                 return -ENOSYS;
1200         }
1201
1202         return status;
1203 }
1204
1205 static int video_outputsw_set(int status)
1206 {
1207         int autosw;
1208         int res = 0;
1209
1210         switch (video_supported) {
1211         case TPACPI_VIDEO_570:
1212                 res = acpi_evalf(NULL, NULL,
1213                                  "\\_SB.PHS2", "vdd",
1214                                  TP_ACPI_VIDEO_570_PHS2CMD,
1215                                  status | TP_ACPI_VIDEO_570_PHS2SET);
1216                 break;
1217         case TPACPI_VIDEO_770:
1218                 autosw = video_autosw_get();
1219                 if (autosw < 0)
1220                         return autosw;
1221
1222                 res = video_autosw_set(1);
1223                 if (res)
1224                         return res;
1225                 res = acpi_evalf(vid_handle, NULL,
1226                                  "ASWT", "vdd", status * 0x100, 0);
1227                 if (!autosw && video_autosw_set(autosw)) {
1228                         printk(IBM_ERR "video auto-switch left enabled due to error\n");
1229                         return -EIO;
1230                 }
1231                 break;
1232         case TPACPI_VIDEO_NEW:
1233                 res = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
1234                         acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
1235                 break;
1236         default:
1237                 return -ENOSYS;
1238         }
1239
1240         return (res)? 0 : -EIO;
1241 }
1242
1243 static int video_autosw_get(void)
1244 {
1245         int autosw = 0;
1246
1247         switch (video_supported) {
1248         case TPACPI_VIDEO_570:
1249                 if (!acpi_evalf(vid_handle, &autosw, "SWIT", "d"))
1250                         return -EIO;
1251                 break;
1252         case TPACPI_VIDEO_770:
1253         case TPACPI_VIDEO_NEW:
1254                 if (!acpi_evalf(vid_handle, &autosw, "^VDEE", "d"))
1255                         return -EIO;
1256                 break;
1257         default:
1258                 return -ENOSYS;
1259         }
1260
1261         return autosw & 1;
1262 }
1263
1264 static int video_autosw_set(int enable)
1265 {
1266         if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable)? 1 : 0))
1267                 return -EIO;
1268         return 0;
1269 }
1270
1271 static int video_outputsw_cycle(void)
1272 {
1273         int autosw = video_autosw_get();
1274         int res;
1275
1276         if (autosw < 0)
1277                 return autosw;
1278
1279         switch (video_supported) {
1280         case TPACPI_VIDEO_570:
1281                 res = video_autosw_set(1);
1282                 if (res)
1283                         return res;
1284                 res = acpi_evalf(ec_handle, NULL, "_Q16", "v");
1285                 break;
1286         case TPACPI_VIDEO_770:
1287         case TPACPI_VIDEO_NEW:
1288                 res = video_autosw_set(1);
1289                 if (res)
1290                         return res;
1291                 res = acpi_evalf(vid_handle, NULL, "VSWT", "v");
1292                 break;
1293         default:
1294                 return -ENOSYS;
1295         }
1296         if (!autosw && video_autosw_set(autosw)) {
1297                 printk(IBM_ERR "video auto-switch left enabled due to error\n");
1298                 return -EIO;
1299         }
1300
1301         return (res)? 0 : -EIO;
1302 }
1303
1304 static int video_expand_toggle(void)
1305 {
1306         switch (video_supported) {
1307         case TPACPI_VIDEO_570:
1308                 return acpi_evalf(ec_handle, NULL, "_Q17", "v")?
1309                         0 : -EIO;
1310         case TPACPI_VIDEO_770:
1311                 return acpi_evalf(vid_handle, NULL, "VEXP", "v")?
1312                         0 : -EIO;
1313         case TPACPI_VIDEO_NEW:
1314                 return acpi_evalf(NULL, NULL, "\\VEXP", "v")?
1315                         0 : -EIO;
1316         default:
1317                 return -ENOSYS;
1318         }
1319         /* not reached */
1320 }
1321
1322 static int video_read(char *p)
1323 {
1324         int status, autosw;
1325         int len = 0;
1326
1327         if (video_supported == TPACPI_VIDEO_NONE) {
1328                 len += sprintf(p + len, "status:\t\tnot supported\n");
1329                 return len;
1330         }
1331
1332         status = video_outputsw_get();
1333         if (status < 0)
1334                 return status;
1335
1336         autosw = video_autosw_get();
1337         if (autosw < 0)
1338                 return autosw;
1339
1340         len += sprintf(p + len, "status:\t\tsupported\n");
1341         len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
1342         len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
1343         if (video_supported == TPACPI_VIDEO_NEW)
1344                 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
1345         len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
1346         len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
1347         len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
1348         if (video_supported == TPACPI_VIDEO_NEW)
1349                 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
1350         len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
1351         len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
1352
1353         return len;
1354 }
1355
1356 static int video_write(char *buf)
1357 {
1358         char *cmd;
1359         int enable, disable, status;
1360         int res;
1361
1362         if (video_supported == TPACPI_VIDEO_NONE)
1363                 return -ENODEV;
1364
1365         enable = 0;
1366         disable = 0;
1367
1368         while ((cmd = next_cmd(&buf))) {
1369                 if (strlencmp(cmd, "lcd_enable") == 0) {
1370                         enable |= TP_ACPI_VIDEO_S_LCD;
1371                 } else if (strlencmp(cmd, "lcd_disable") == 0) {
1372                         disable |= TP_ACPI_VIDEO_S_LCD;
1373                 } else if (strlencmp(cmd, "crt_enable") == 0) {
1374                         enable |= TP_ACPI_VIDEO_S_CRT;
1375                 } else if (strlencmp(cmd, "crt_disable") == 0) {
1376                         disable |= TP_ACPI_VIDEO_S_CRT;
1377                 } else if (video_supported == TPACPI_VIDEO_NEW &&
1378                            strlencmp(cmd, "dvi_enable") == 0) {
1379                         enable |= TP_ACPI_VIDEO_S_DVI;
1380                 } else if (video_supported == TPACPI_VIDEO_NEW &&
1381                            strlencmp(cmd, "dvi_disable") == 0) {
1382                         disable |= TP_ACPI_VIDEO_S_DVI;
1383                 } else if (strlencmp(cmd, "auto_enable") == 0) {
1384                         res = video_autosw_set(1);
1385                         if (res)
1386                                 return res;
1387                 } else if (strlencmp(cmd, "auto_disable") == 0) {
1388                         res = video_autosw_set(0);
1389                         if (res)
1390                                 return res;
1391                 } else if (strlencmp(cmd, "video_switch") == 0) {
1392                         res = video_outputsw_cycle();
1393                         if (res)
1394                                 return res;
1395                 } else if (strlencmp(cmd, "expand_toggle") == 0) {
1396                         res = video_expand_toggle();
1397                         if (res)
1398                                 return res;
1399                 } else
1400                         return -EINVAL;
1401         }
1402
1403         if (enable || disable) {
1404                 status = video_outputsw_get();
1405                 if (status < 0)
1406                         return status;
1407                 res = video_outputsw_set((status & ~disable) | enable);
1408                 if (res)
1409                         return res;
1410         }
1411
1412         return 0;
1413 }
1414
1415 static struct ibm_struct video_driver_data = {
1416         .name = "video",
1417         .read = video_read,
1418         .write = video_write,
1419         .exit = video_exit,
1420 };
1421
1422 /*************************************************************************
1423  * Light (thinklight) subdriver
1424  */
1425
1426 IBM_HANDLE(lght, root, "\\LGHT");       /* A21e, A2xm/p, T20-22, X20-21 */
1427 IBM_HANDLE(ledb, ec, "LEDB");           /* G4x */
1428
1429 static int __init light_init(struct ibm_init_struct *iibm)
1430 {
1431         vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
1432
1433         IBM_ACPIHANDLE_INIT(ledb);
1434         IBM_ACPIHANDLE_INIT(lght);
1435         IBM_ACPIHANDLE_INIT(cmos);
1436
1437         /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
1438         tp_features.light = (cmos_handle || lght_handle) && !ledb_handle;
1439
1440         if (tp_features.light)
1441                 /* light status not supported on
1442                    570, 600e/x, 770e, 770x, G4x, R30, R31, R32, X20 */
1443                 tp_features.light_status =
1444                         acpi_evalf(ec_handle, NULL, "KBLT", "qv");
1445
1446         vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
1447                 str_supported(tp_features.light));
1448
1449         return (tp_features.light)? 0 : 1;
1450 }
1451
1452 static int light_read(char *p)
1453 {
1454         int len = 0;
1455         int status = 0;
1456
1457         if (!tp_features.light) {
1458                 len += sprintf(p + len, "status:\t\tnot supported\n");
1459         } else if (!tp_features.light_status) {
1460                 len += sprintf(p + len, "status:\t\tunknown\n");
1461                 len += sprintf(p + len, "commands:\ton, off\n");
1462         } else {
1463                 if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
1464                         return -EIO;
1465                 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
1466                 len += sprintf(p + len, "commands:\ton, off\n");
1467         }
1468
1469         return len;
1470 }
1471
1472 static int light_write(char *buf)
1473 {
1474         int cmos_cmd, lght_cmd;
1475         char *cmd;
1476         int success;
1477
1478         if (!tp_features.light)
1479                 return -ENODEV;
1480
1481         while ((cmd = next_cmd(&buf))) {
1482                 if (strlencmp(cmd, "on") == 0) {
1483                         cmos_cmd = 0x0c;
1484                         lght_cmd = 1;
1485                 } else if (strlencmp(cmd, "off") == 0) {
1486                         cmos_cmd = 0x0d;
1487                         lght_cmd = 0;
1488                 } else
1489                         return -EINVAL;
1490
1491                 success = cmos_handle ?
1492                     acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
1493                     acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
1494                 if (!success)
1495                         return -EIO;
1496         }
1497
1498         return 0;
1499 }
1500
1501 static struct ibm_struct light_driver_data = {
1502         .name = "light",
1503         .read = light_read,
1504         .write = light_write,
1505 };
1506
1507 /*************************************************************************
1508  * Dock subdriver
1509  */
1510
1511 #ifdef CONFIG_THINKPAD_ACPI_DOCK
1512
1513 IBM_HANDLE(dock, root, "\\_SB.GDCK",    /* X30, X31, X40 */
1514            "\\_SB.PCI0.DOCK",   /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
1515            "\\_SB.PCI0.PCI1.DOCK",      /* all others */
1516            "\\_SB.PCI.ISA.SLCE",        /* 570 */
1517     );                          /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
1518
1519 /* don't list other alternatives as we install a notify handler on the 570 */
1520 IBM_HANDLE(pci, root, "\\_SB.PCI");     /* 570 */
1521
1522 static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = {
1523         {
1524          .notify = dock_notify,
1525          .handle = &dock_handle,
1526          .type = ACPI_SYSTEM_NOTIFY,
1527         },
1528         {
1529          .hid = IBM_PCI_HID,
1530          .notify = dock_notify,
1531          .handle = &pci_handle,
1532          .type = ACPI_SYSTEM_NOTIFY,
1533         },
1534 };
1535
1536 static struct ibm_struct dock_driver_data[2] = {
1537         {
1538          .name = "dock",
1539          .read = dock_read,
1540          .write = dock_write,
1541          .acpi = &ibm_dock_acpidriver[0],
1542         },
1543         {
1544          .name = "dock",
1545          .acpi = &ibm_dock_acpidriver[1],
1546         },
1547 };
1548
1549 #define dock_docked() (_sta(dock_handle) & 1)
1550
1551 static int __init dock_init(struct ibm_init_struct *iibm)
1552 {
1553         vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n");
1554
1555         IBM_ACPIHANDLE_INIT(dock);
1556
1557         vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n",
1558                 str_supported(dock_handle != NULL));
1559
1560         return (dock_handle)? 0 : 1;
1561 }
1562
1563 static int __init dock_init2(struct ibm_init_struct *iibm)
1564 {
1565         int dock2_needed;
1566
1567         vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver part 2\n");
1568
1569         if (dock_driver_data[0].flags.acpi_driver_registered &&
1570             dock_driver_data[0].flags.acpi_notify_installed) {
1571                 IBM_ACPIHANDLE_INIT(pci);
1572                 dock2_needed = (pci_handle != NULL);
1573                 vdbg_printk(TPACPI_DBG_INIT,
1574                             "dock PCI handler for the TP 570 is %s\n",
1575                             str_supported(dock2_needed));
1576         } else {
1577                 vdbg_printk(TPACPI_DBG_INIT,
1578                 "dock subdriver part 2 not required\n");
1579                 dock2_needed = 0;
1580         }
1581
1582         return (dock2_needed)? 0 : 1;
1583 }
1584
1585 static void dock_notify(struct ibm_struct *ibm, u32 event)
1586 {
1587         int docked = dock_docked();
1588         int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, IBM_PCI_HID);
1589
1590         if (event == 1 && !pci) /* 570 */
1591                 acpi_bus_generate_event(ibm->acpi->device, event, 1);   /* button */
1592         else if (event == 1 && pci)     /* 570 */
1593                 acpi_bus_generate_event(ibm->acpi->device, event, 3);   /* dock */
1594         else if (event == 3 && docked)
1595                 acpi_bus_generate_event(ibm->acpi->device, event, 1);   /* button */
1596         else if (event == 3 && !docked)
1597                 acpi_bus_generate_event(ibm->acpi->device, event, 2);   /* undock */
1598         else if (event == 0 && docked)
1599                 acpi_bus_generate_event(ibm->acpi->device, event, 3);   /* dock */
1600         else {
1601                 printk(IBM_ERR "unknown dock event %d, status %d\n",
1602                        event, _sta(dock_handle));
1603                 acpi_bus_generate_event(ibm->acpi->device, event, 0);   /* unknown */
1604         }
1605 }
1606
1607 static int dock_read(char *p)
1608 {
1609         int len = 0;
1610         int docked = dock_docked();
1611
1612         if (!dock_handle)
1613                 len += sprintf(p + len, "status:\t\tnot supported\n");
1614         else if (!docked)
1615                 len += sprintf(p + len, "status:\t\tundocked\n");
1616         else {
1617                 len += sprintf(p + len, "status:\t\tdocked\n");
1618                 len += sprintf(p + len, "commands:\tdock, undock\n");
1619         }
1620
1621         return len;
1622 }
1623
1624 static int dock_write(char *buf)
1625 {
1626         char *cmd;
1627
1628         if (!dock_docked())
1629                 return -ENODEV;
1630
1631         while ((cmd = next_cmd(&buf))) {
1632                 if (strlencmp(cmd, "undock") == 0) {
1633                         if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
1634                             !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
1635                                 return -EIO;
1636                 } else if (strlencmp(cmd, "dock") == 0) {
1637                         if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
1638                                 return -EIO;
1639                 } else
1640                         return -EINVAL;
1641         }
1642
1643         return 0;
1644 }
1645
1646 #endif /* CONFIG_THINKPAD_ACPI_DOCK */
1647
1648 /*************************************************************************
1649  * Bay subdriver
1650  */
1651
1652 #ifdef CONFIG_THINKPAD_ACPI_BAY
1653 IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",        /* 570 */
1654            "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
1655            "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
1656            "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
1657            );                           /* A21e, R30, R31 */
1658 IBM_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */
1659            "_EJ0",              /* all others */
1660            );                   /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
1661 IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV",     /* A3x, R32 */
1662            "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
1663            );                           /* all others */
1664 IBM_HANDLE(bay2_ej, bay2, "_EJ3",       /* 600e/x, 770e, A3x */
1665            "_EJ0",                      /* 770x */
1666            );                           /* all others */
1667
1668 static int __init bay_init(struct ibm_init_struct *iibm)
1669 {
1670         vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n");
1671
1672         IBM_ACPIHANDLE_INIT(bay);
1673         if (bay_handle)
1674                 IBM_ACPIHANDLE_INIT(bay_ej);
1675         IBM_ACPIHANDLE_INIT(bay2);
1676         if (bay2_handle)
1677                 IBM_ACPIHANDLE_INIT(bay2_ej);
1678
1679         tp_features.bay_status = bay_handle &&
1680                 acpi_evalf(bay_handle, NULL, "_STA", "qv");
1681         tp_features.bay_status2 = bay2_handle &&
1682                 acpi_evalf(bay2_handle, NULL, "_STA", "qv");
1683
1684         tp_features.bay_eject = bay_handle && bay_ej_handle &&
1685                 (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
1686         tp_features.bay_eject2 = bay2_handle && bay2_ej_handle &&
1687                 (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
1688
1689         vdbg_printk(TPACPI_DBG_INIT,
1690                 "bay 1: status %s, eject %s; bay 2: status %s, eject %s\n",
1691                 str_supported(tp_features.bay_status),
1692                 str_supported(tp_features.bay_eject),
1693                 str_supported(tp_features.bay_status2),
1694                 str_supported(tp_features.bay_eject2));
1695
1696         return (tp_features.bay_status || tp_features.bay_eject ||
1697                 tp_features.bay_status2 || tp_features.bay_eject2)? 0 : 1;
1698 }
1699
1700 static void bay_notify(struct ibm_struct *ibm, u32 event)
1701 {
1702         acpi_bus_generate_event(ibm->acpi->device, event, 0);
1703 }
1704
1705 #define bay_occupied(b) (_sta(b##_handle) & 1)
1706
1707 static int bay_read(char *p)
1708 {
1709         int len = 0;
1710         int occupied = bay_occupied(bay);
1711         int occupied2 = bay_occupied(bay2);
1712         int eject, eject2;
1713
1714         len += sprintf(p + len, "status:\t\t%s\n",
1715                 tp_features.bay_status ?
1716                         (occupied ? "occupied" : "unoccupied") :
1717                                 "not supported");
1718         if (tp_features.bay_status2)
1719                 len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
1720                                "occupied" : "unoccupied");
1721
1722         eject = tp_features.bay_eject && occupied;
1723         eject2 = tp_features.bay_eject2 && occupied2;
1724
1725         if (eject && eject2)
1726                 len += sprintf(p + len, "commands:\teject, eject2\n");
1727         else if (eject)
1728                 len += sprintf(p + len, "commands:\teject\n");
1729         else if (eject2)
1730                 len += sprintf(p + len, "commands:\teject2\n");
1731
1732         return len;
1733 }
1734
1735 static int bay_write(char *buf)
1736 {
1737         char *cmd;
1738
1739         if (!tp_features.bay_eject && !tp_features.bay_eject2)
1740                 return -ENODEV;
1741
1742         while ((cmd = next_cmd(&buf))) {
1743                 if (tp_features.bay_eject && strlencmp(cmd, "eject") == 0) {
1744                         if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
1745                                 return -EIO;
1746                 } else if (tp_features.bay_eject2 &&
1747                            strlencmp(cmd, "eject2") == 0) {
1748                         if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
1749                                 return -EIO;
1750                 } else
1751                         return -EINVAL;
1752         }
1753
1754         return 0;
1755 }
1756
1757 static struct tp_acpi_drv_struct ibm_bay_acpidriver = {
1758         .notify = bay_notify,
1759         .handle = &bay_handle,
1760         .type = ACPI_SYSTEM_NOTIFY,
1761 };
1762
1763 static struct ibm_struct bay_driver_data = {
1764         .name = "bay",
1765         .read = bay_read,
1766         .write = bay_write,
1767         .acpi = &ibm_bay_acpidriver,
1768 };
1769
1770 #endif /* CONFIG_THINKPAD_ACPI_BAY */
1771
1772 /*************************************************************************
1773  * CMOS subdriver
1774  */
1775
1776 /* sysfs cmos_command -------------------------------------------------- */
1777 static ssize_t cmos_command_store(struct device *dev,
1778                             struct device_attribute *attr,
1779                             const char *buf, size_t count)
1780 {
1781         unsigned long cmos_cmd;
1782         int res;
1783
1784         if (parse_strtoul(buf, 21, &cmos_cmd))
1785                 return -EINVAL;
1786
1787         res = issue_thinkpad_cmos_command(cmos_cmd);
1788         return (res)? res : count;
1789 }
1790
1791 static struct device_attribute dev_attr_cmos_command =
1792         __ATTR(cmos_command, S_IWUSR, NULL, cmos_command_store);
1793
1794 /* --------------------------------------------------------------------- */
1795
1796 static int __init cmos_init(struct ibm_init_struct *iibm)
1797 {
1798         int res;
1799
1800         vdbg_printk(TPACPI_DBG_INIT,
1801                 "initializing cmos commands subdriver\n");
1802
1803         IBM_ACPIHANDLE_INIT(cmos);
1804
1805         vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n",
1806                 str_supported(cmos_handle != NULL));
1807
1808         res = device_create_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
1809         if (res)
1810                 return res;
1811
1812         return (cmos_handle)? 0 : 1;
1813 }
1814
1815 static void cmos_exit(void)
1816 {
1817         device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
1818 }
1819
1820 static int cmos_read(char *p)
1821 {
1822         int len = 0;
1823
1824         /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
1825            R30, R31, T20-22, X20-21 */
1826         if (!cmos_handle)
1827                 len += sprintf(p + len, "status:\t\tnot supported\n");
1828         else {
1829                 len += sprintf(p + len, "status:\t\tsupported\n");
1830                 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
1831         }
1832
1833         return len;
1834 }
1835
1836 static int cmos_write(char *buf)
1837 {
1838         char *cmd;
1839         int cmos_cmd, res;
1840
1841         while ((cmd = next_cmd(&buf))) {
1842                 if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
1843                     cmos_cmd >= 0 && cmos_cmd <= 21) {
1844                         /* cmos_cmd set */
1845                 } else
1846                         return -EINVAL;
1847
1848                 res = issue_thinkpad_cmos_command(cmos_cmd);
1849                 if (res)
1850                         return res;
1851         }
1852
1853         return 0;
1854 }
1855
1856 static struct ibm_struct cmos_driver_data = {
1857         .name = "cmos",
1858         .read = cmos_read,
1859         .write = cmos_write,
1860         .exit = cmos_exit,
1861 };
1862
1863 /*************************************************************************
1864  * LED subdriver
1865  */
1866
1867 static enum led_access_mode led_supported;
1868
1869 IBM_HANDLE(led, ec, "SLED",     /* 570 */
1870            "SYSL",              /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
1871            "LED",               /* all others */
1872            );                   /* R30, R31 */
1873
1874 static int __init led_init(struct ibm_init_struct *iibm)
1875 {
1876         vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
1877
1878         IBM_ACPIHANDLE_INIT(led);
1879
1880         if (!led_handle)
1881                 /* led not supported on R30, R31 */
1882                 led_supported = TPACPI_LED_NONE;
1883         else if (strlencmp(led_path, "SLED") == 0)
1884                 /* 570 */
1885                 led_supported = TPACPI_LED_570;
1886         else if (strlencmp(led_path, "SYSL") == 0)
1887                 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
1888                 led_supported = TPACPI_LED_OLD;
1889         else
1890                 /* all others */
1891                 led_supported = TPACPI_LED_NEW;
1892
1893         vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n",
1894                 str_supported(led_supported), led_supported);
1895
1896         return (led_supported != TPACPI_LED_NONE)? 0 : 1;
1897 }
1898
1899 #define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
1900
1901 static int led_read(char *p)
1902 {
1903         int len = 0;
1904
1905         if (!led_supported) {
1906                 len += sprintf(p + len, "status:\t\tnot supported\n");
1907                 return len;
1908         }
1909         len += sprintf(p + len, "status:\t\tsupported\n");
1910
1911         if (led_supported == TPACPI_LED_570) {
1912                 /* 570 */
1913                 int i, status;
1914                 for (i = 0; i < 8; i++) {
1915                         if (!acpi_evalf(ec_handle,
1916                                         &status, "GLED", "dd", 1 << i))
1917                                 return -EIO;
1918                         len += sprintf(p + len, "%d:\t\t%s\n",
1919                                        i, led_status(status));
1920                 }
1921         }
1922
1923         len += sprintf(p + len, "commands:\t"
1924                        "<led> on, <led> off, <led> blink (<led> is 0-7)\n");
1925
1926         return len;
1927 }
1928
1929 /* off, on, blink */
1930 static const int led_sled_arg1[] = { 0, 1, 3 };
1931 static const int led_exp_hlbl[] = { 0, 0, 1 };  /* led# * */
1932 static const int led_exp_hlcl[] = { 0, 1, 1 };  /* led# * */
1933 static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
1934
1935 static int led_write(char *buf)
1936 {
1937         char *cmd;
1938         int led, ind, ret;
1939
1940         if (!led_supported)
1941                 return -ENODEV;
1942
1943         while ((cmd = next_cmd(&buf))) {
1944                 if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7)
1945                         return -EINVAL;
1946
1947                 if (strstr(cmd, "off")) {
1948                         ind = 0;
1949                 } else if (strstr(cmd, "on")) {
1950                         ind = 1;
1951                 } else if (strstr(cmd, "blink")) {
1952                         ind = 2;
1953                 } else
1954                         return -EINVAL;
1955
1956                 if (led_supported == TPACPI_LED_570) {
1957                         /* 570 */
1958                         led = 1 << led;
1959                         if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
1960                                         led, led_sled_arg1[ind]))
1961                                 return -EIO;
1962                 } else if (led_supported == TPACPI_LED_OLD) {
1963                         /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
1964                         led = 1 << led;
1965                         ret = ec_write(TPACPI_LED_EC_HLMS, led);
1966                         if (ret >= 0)
1967                                 ret =
1968                                     ec_write(TPACPI_LED_EC_HLBL,
1969                                              led * led_exp_hlbl[ind]);
1970                         if (ret >= 0)
1971                                 ret =
1972                                     ec_write(TPACPI_LED_EC_HLCL,
1973                                              led * led_exp_hlcl[ind]);
1974                         if (ret < 0)
1975                                 return ret;
1976                 } else {
1977                         /* all others */
1978                         if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
1979                                         led, led_led_arg1[ind]))
1980                                 return -EIO;
1981                 }
1982         }
1983
1984         return 0;
1985 }
1986
1987 static struct ibm_struct led_driver_data = {
1988         .name = "led",
1989         .read = led_read,
1990         .write = led_write,
1991 };
1992
1993 /*************************************************************************
1994  * Beep subdriver
1995  */
1996
1997 IBM_HANDLE(beep, ec, "BEEP");   /* all except R30, R31 */
1998
1999 static int __init beep_init(struct ibm_init_struct *iibm)
2000 {
2001         vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n");
2002
2003         IBM_ACPIHANDLE_INIT(beep);
2004
2005         vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n",
2006                 str_supported(beep_handle != NULL));
2007
2008         return (beep_handle)? 0 : 1;
2009 }
2010
2011 static int beep_read(char *p)
2012 {
2013         int len = 0;
2014
2015         if (!beep_handle)
2016                 len += sprintf(p + len, "status:\t\tnot supported\n");
2017         else {
2018                 len += sprintf(p + len, "status:\t\tsupported\n");
2019                 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
2020         }
2021
2022         return len;
2023 }
2024
2025 static int beep_write(char *buf)
2026 {
2027         char *cmd;
2028         int beep_cmd;
2029
2030         if (!beep_handle)
2031                 return -ENODEV;
2032
2033         while ((cmd = next_cmd(&buf))) {
2034                 if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
2035                     beep_cmd >= 0 && beep_cmd <= 17) {
2036                         /* beep_cmd set */
2037                 } else
2038                         return -EINVAL;
2039                 if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0))
2040                         return -EIO;
2041         }
2042
2043         return 0;
2044 }
2045
2046 static struct ibm_struct beep_driver_data = {
2047         .name = "beep",
2048         .read = beep_read,
2049         .write = beep_write,
2050 };
2051
2052 /*************************************************************************
2053  * Thermal subdriver
2054  */
2055
2056 static enum thermal_access_mode thermal_read_mode;
2057
2058 /* sysfs temp##_input -------------------------------------------------- */
2059
2060 static ssize_t thermal_temp_input_show(struct device *dev,
2061                            struct device_attribute *attr,
2062                            char *buf)
2063 {
2064         struct sensor_device_attribute *sensor_attr =
2065                                         to_sensor_dev_attr(attr);
2066         int idx = sensor_attr->index;
2067         s32 value;
2068         int res;
2069
2070         res = thermal_get_sensor(idx, &value);
2071         if (res)
2072                 return res;
2073         if (value == TP_EC_THERMAL_TMP_NA * 1000)
2074                 return -ENXIO;
2075
2076         return snprintf(buf, PAGE_SIZE, "%d\n", value);
2077 }
2078
2079 #define THERMAL_SENSOR_ATTR_TEMP(_idxA, _idxB) \
2080          SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, thermal_temp_input_show, NULL, _idxB)
2081
2082 static struct sensor_device_attribute sensor_dev_attr_thermal_temp_input[] = {
2083         THERMAL_SENSOR_ATTR_TEMP(1, 0),
2084         THERMAL_SENSOR_ATTR_TEMP(2, 1),
2085         THERMAL_SENSOR_ATTR_TEMP(3, 2),
2086         THERMAL_SENSOR_ATTR_TEMP(4, 3),
2087         THERMAL_SENSOR_ATTR_TEMP(5, 4),
2088         THERMAL_SENSOR_ATTR_TEMP(6, 5),
2089         THERMAL_SENSOR_ATTR_TEMP(7, 6),
2090         THERMAL_SENSOR_ATTR_TEMP(8, 7),
2091         THERMAL_SENSOR_ATTR_TEMP(9, 8),
2092         THERMAL_SENSOR_ATTR_TEMP(10, 9),
2093         THERMAL_SENSOR_ATTR_TEMP(11, 10),
2094         THERMAL_SENSOR_ATTR_TEMP(12, 11),
2095         THERMAL_SENSOR_ATTR_TEMP(13, 12),
2096         THERMAL_SENSOR_ATTR_TEMP(14, 13),
2097         THERMAL_SENSOR_ATTR_TEMP(15, 14),
2098         THERMAL_SENSOR_ATTR_TEMP(16, 15),
2099 };
2100
2101 #define THERMAL_ATTRS(X) \
2102         &sensor_dev_attr_thermal_temp_input[X].dev_attr.attr
2103
2104 static struct attribute *thermal_temp_input_attr[] = {
2105         THERMAL_ATTRS(8),
2106         THERMAL_ATTRS(9),
2107         THERMAL_ATTRS(10),
2108         THERMAL_ATTRS(11),
2109         THERMAL_ATTRS(12),
2110         THERMAL_ATTRS(13),
2111         THERMAL_ATTRS(14),
2112         THERMAL_ATTRS(15),
2113         THERMAL_ATTRS(0),
2114         THERMAL_ATTRS(1),
2115         THERMAL_ATTRS(2),
2116         THERMAL_ATTRS(3),
2117         THERMAL_ATTRS(4),
2118         THERMAL_ATTRS(5),
2119         THERMAL_ATTRS(6),
2120         THERMAL_ATTRS(7),
2121         NULL
2122 };
2123
2124 static const struct attribute_group thermal_temp_input16_group = {
2125         .attrs = thermal_temp_input_attr
2126 };
2127
2128 static const struct attribute_group thermal_temp_input8_group = {
2129         .attrs = &thermal_temp_input_attr[8]
2130 };
2131
2132 #undef THERMAL_SENSOR_ATTR_TEMP
2133 #undef THERMAL_ATTRS
2134
2135 /* --------------------------------------------------------------------- */
2136
2137 static int __init thermal_init(struct ibm_init_struct *iibm)
2138 {
2139         u8 t, ta1, ta2;
2140         int i;
2141         int acpi_tmp7;
2142         int res;
2143
2144         vdbg_printk(TPACPI_DBG_INIT, "initializing thermal subdriver\n");
2145
2146         acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
2147
2148         if (ibm_thinkpad_ec_found && experimental) {
2149                 /*
2150                  * Direct EC access mode: sensors at registers
2151                  * 0x78-0x7F, 0xC0-0xC7.  Registers return 0x00 for
2152                  * non-implemented, thermal sensors return 0x80 when
2153                  * not available
2154                  */
2155
2156                 ta1 = ta2 = 0;
2157                 for (i = 0; i < 8; i++) {
2158                         if (acpi_ec_read(TP_EC_THERMAL_TMP0 + i, &t)) {
2159                                 ta1 |= t;
2160                         } else {
2161                                 ta1 = 0;
2162                                 break;
2163                         }
2164                         if (acpi_ec_read(TP_EC_THERMAL_TMP8 + i, &t)) {
2165                                 ta2 |= t;
2166                         } else {
2167                                 ta1 = 0;
2168                                 break;
2169                         }
2170                 }
2171                 if (ta1 == 0) {
2172                         /* This is sheer paranoia, but we handle it anyway */
2173                         if (acpi_tmp7) {
2174                                 printk(IBM_ERR
2175                                        "ThinkPad ACPI EC access misbehaving, "
2176                                        "falling back to ACPI TMPx access mode\n");
2177                                 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
2178                         } else {
2179                                 printk(IBM_ERR
2180                                        "ThinkPad ACPI EC access misbehaving, "
2181                                        "disabling thermal sensors access\n");
2182                                 thermal_read_mode = TPACPI_THERMAL_NONE;
2183                         }
2184                 } else {
2185                         thermal_read_mode =
2186                             (ta2 != 0) ?
2187                             TPACPI_THERMAL_TPEC_16 : TPACPI_THERMAL_TPEC_8;
2188                 }
2189         } else if (acpi_tmp7) {
2190                 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
2191                         /* 600e/x, 770e, 770x */
2192                         thermal_read_mode = TPACPI_THERMAL_ACPI_UPDT;
2193                 } else {
2194                         /* Standard ACPI TMPx access, max 8 sensors */
2195                         thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
2196                 }
2197         } else {
2198                 /* temperatures not supported on 570, G4x, R30, R31, R32 */
2199                 thermal_read_mode = TPACPI_THERMAL_NONE;
2200         }
2201
2202         vdbg_printk(TPACPI_DBG_INIT, "thermal is %s, mode %d\n",
2203                 str_supported(thermal_read_mode != TPACPI_THERMAL_NONE),
2204                 thermal_read_mode);
2205
2206         switch(thermal_read_mode) {
2207         case TPACPI_THERMAL_TPEC_16:
2208                 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
2209                                 &thermal_temp_input16_group);
2210                 if (res)
2211                         return res;
2212                 break;
2213         case TPACPI_THERMAL_TPEC_8:
2214         case TPACPI_THERMAL_ACPI_TMP07:
2215         case TPACPI_THERMAL_ACPI_UPDT:
2216                 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
2217                                 &thermal_temp_input8_group);
2218                 if (res)
2219                         return res;
2220                 break;
2221         case TPACPI_THERMAL_NONE:
2222         default:
2223                 return 1;
2224         }
2225
2226         return 0;
2227 }
2228
2229 static void thermal_exit(void)
2230 {
2231         switch(thermal_read_mode) {
2232         case TPACPI_THERMAL_TPEC_16:
2233                 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
2234                                    &thermal_temp_input16_group);
2235                 break;
2236         case TPACPI_THERMAL_TPEC_8:
2237         case TPACPI_THERMAL_ACPI_TMP07:
2238         case TPACPI_THERMAL_ACPI_UPDT:
2239                 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
2240                                    &thermal_temp_input16_group);
2241                 break;
2242         case TPACPI_THERMAL_NONE:
2243         default:
2244                 break;
2245         }
2246 }
2247
2248 /* idx is zero-based */
2249 static int thermal_get_sensor(int idx, s32 *value)
2250 {
2251         int t;
2252         s8 tmp;
2253         char tmpi[5];
2254
2255         t = TP_EC_THERMAL_TMP0;
2256
2257         switch (thermal_read_mode) {
2258 #if TPACPI_MAX_THERMAL_SENSORS >= 16
2259         case TPACPI_THERMAL_TPEC_16:
2260                 if (idx >= 8 && idx <= 15) {
2261                         t = TP_EC_THERMAL_TMP8;
2262                         idx -= 8;
2263                 }
2264                 /* fallthrough */
2265 #endif
2266         case TPACPI_THERMAL_TPEC_8:
2267                 if (idx <= 7) {
2268                         if (!acpi_ec_read(t + idx, &tmp))
2269                                 return -EIO;
2270                         *value = tmp * 1000;
2271                         return 0;
2272                 }
2273                 break;
2274
2275         case TPACPI_THERMAL_ACPI_UPDT:
2276                 if (idx <= 7) {
2277                         snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
2278                         if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
2279                                 return -EIO;
2280                         if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
2281                                 return -EIO;
2282                         *value = (t - 2732) * 100;
2283                         return 0;
2284                 }
2285                 break;
2286
2287         case TPACPI_THERMAL_ACPI_TMP07:
2288                 if (idx <= 7) {
2289                         snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
2290                         if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
2291                                 return -EIO;
2292                         *value = t * 1000;
2293                         return 0;
2294                 }
2295                 break;
2296
2297         case TPACPI_THERMAL_NONE:
2298         default:
2299                 return -ENOSYS;
2300         }
2301
2302         return -EINVAL;
2303 }
2304
2305 static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
2306 {
2307         int res, i;
2308         int n;
2309
2310         n = 8;
2311         i = 0;
2312
2313         if (!s)
2314                 return -EINVAL;
2315
2316         if (thermal_read_mode == TPACPI_THERMAL_TPEC_16)
2317                 n = 16;
2318
2319         for(i = 0 ; i < n; i++) {
2320                 res = thermal_get_sensor(i, &s->temp[i]);
2321                 if (res)
2322                         return res;
2323         }
2324
2325         return n;
2326 }
2327
2328 static int thermal_read(char *p)
2329 {
2330         int len = 0;
2331         int n, i;
2332         struct ibm_thermal_sensors_struct t;
2333
2334         n = thermal_get_sensors(&t);
2335         if (unlikely(n < 0))
2336                 return n;
2337
2338         len += sprintf(p + len, "temperatures:\t");
2339
2340         if (n > 0) {
2341                 for (i = 0; i < (n - 1); i++)
2342                         len += sprintf(p + len, "%d ", t.temp[i] / 1000);
2343                 len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
2344         } else
2345                 len += sprintf(p + len, "not supported\n");
2346
2347         return len;
2348 }
2349
2350 static struct ibm_struct thermal_driver_data = {
2351         .name = "thermal",
2352         .read = thermal_read,
2353         .exit = thermal_exit,
2354 };
2355
2356 /*************************************************************************
2357  * EC Dump subdriver
2358  */
2359
2360 static u8 ecdump_regs[256];
2361
2362 static int ecdump_read(char *p)
2363 {
2364         int len = 0;
2365         int i, j;
2366         u8 v;
2367
2368         len += sprintf(p + len, "EC      "
2369                        " +00 +01 +02 +03 +04 +05 +06 +07"
2370                        " +08 +09 +0a +0b +0c +0d +0e +0f\n");
2371         for (i = 0; i < 256; i += 16) {
2372                 len += sprintf(p + len, "EC 0x%02x:", i);
2373                 for (j = 0; j < 16; j++) {
2374                         if (!acpi_ec_read(i + j, &v))
2375                                 break;
2376                         if (v != ecdump_regs[i + j])
2377                                 len += sprintf(p + len, " *%02x", v);
2378                         else
2379                                 len += sprintf(p + len, "  %02x", v);
2380                         ecdump_regs[i + j] = v;
2381                 }
2382                 len += sprintf(p + len, "\n");
2383                 if (j != 16)
2384                         break;
2385         }
2386
2387         /* These are way too dangerous to advertise openly... */
2388 #if 0
2389         len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
2390                        " (<offset> is 00-ff, <value> is 00-ff)\n");
2391         len += sprintf(p + len, "commands:\t0x<offset> <value>  "
2392                        " (<offset> is 00-ff, <value> is 0-255)\n");
2393 #endif
2394         return len;
2395 }
2396
2397 static int ecdump_write(char *buf)
2398 {
2399         char *cmd;
2400         int i, v;
2401
2402         while ((cmd = next_cmd(&buf))) {
2403                 if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
2404                         /* i and v set */
2405                 } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
2406                         /* i and v set */
2407                 } else
2408                         return -EINVAL;
2409                 if (i >= 0 && i < 256 && v >= 0 && v < 256) {
2410                         if (!acpi_ec_write(i, v))
2411                                 return -EIO;
2412                 } else
2413                         return -EINVAL;
2414         }
2415
2416         return 0;
2417 }
2418
2419 static struct ibm_struct ecdump_driver_data = {
2420         .name = "ecdump",
2421         .read = ecdump_read,
2422         .write = ecdump_write,
2423         .flags.experimental = 1,
2424 };
2425
2426 /*************************************************************************
2427  * Backlight/brightness subdriver
2428  */
2429
2430 static struct backlight_device *ibm_backlight_device = NULL;
2431
2432 static struct backlight_ops ibm_backlight_data = {
2433         .get_brightness = brightness_get,
2434         .update_status  = brightness_update_status,
2435 };
2436
2437 static int __init brightness_init(struct ibm_init_struct *iibm)
2438 {
2439         int b;
2440
2441         vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n");
2442
2443         b = brightness_get(NULL);
2444         if (b < 0)
2445                 return b;
2446
2447         ibm_backlight_device = backlight_device_register(
2448                                         TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
2449                                         &ibm_backlight_data);
2450         if (IS_ERR(ibm_backlight_device)) {
2451                 printk(IBM_ERR "Could not register backlight device\n");
2452                 return PTR_ERR(ibm_backlight_device);
2453         }
2454         vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n");
2455
2456         ibm_backlight_device->props.max_brightness = 7;
2457         ibm_backlight_device->props.brightness = b;
2458         backlight_update_status(ibm_backlight_device);
2459
2460         return 0;
2461 }
2462
2463 static void brightness_exit(void)
2464 {
2465         if (ibm_backlight_device) {
2466                 vdbg_printk(TPACPI_DBG_EXIT,
2467                             "calling backlight_device_unregister()\n");
2468                 backlight_device_unregister(ibm_backlight_device);
2469                 ibm_backlight_device = NULL;
2470         }
2471 }
2472
2473 static int brightness_update_status(struct backlight_device *bd)
2474 {
2475         return brightness_set(
2476                 (bd->props.fb_blank == FB_BLANK_UNBLANK &&
2477                  bd->props.power == FB_BLANK_UNBLANK) ?
2478                                 bd->props.brightness : 0);
2479 }
2480
2481 static int brightness_get(struct backlight_device *bd)
2482 {
2483         u8 level;
2484         if (!acpi_ec_read(brightness_offset, &level))
2485                 return -EIO;
2486
2487         level &= 0x7;
2488
2489         return level;
2490 }
2491
2492 static int brightness_set(int value)
2493 {
2494         int cmos_cmd, inc, i;
2495         int current_value = brightness_get(NULL);
2496
2497         value &= 7;
2498
2499         cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN;
2500         inc = value > current_value ? 1 : -1;
2501         for (i = current_value; i != value; i += inc) {
2502                 if (issue_thinkpad_cmos_command(cmos_cmd))
2503                         return -EIO;
2504                 if (!acpi_ec_write(brightness_offset, i + inc))
2505                         return -EIO;
2506         }
2507
2508         return 0;
2509 }
2510
2511 static int brightness_read(char *p)
2512 {
2513         int len = 0;
2514         int level;
2515
2516         if ((level = brightness_get(NULL)) < 0) {
2517                 len += sprintf(p + len, "level:\t\tunreadable\n");
2518         } else {
2519                 len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
2520                 len += sprintf(p + len, "commands:\tup, down\n");
2521                 len += sprintf(p + len, "commands:\tlevel <level>"
2522                                " (<level> is 0-7)\n");
2523         }
2524
2525         return len;
2526 }
2527
2528 static int brightness_write(char *buf)
2529 {
2530         int level;
2531         int new_level;
2532         char *cmd;
2533
2534         while ((cmd = next_cmd(&buf))) {
2535                 if ((level = brightness_get(NULL)) < 0)
2536                         return level;
2537                 level &= 7;
2538
2539                 if (strlencmp(cmd, "up") == 0) {
2540                         new_level = level == 7 ? 7 : level + 1;
2541                 } else if (strlencmp(cmd, "down") == 0) {
2542                         new_level = level == 0 ? 0 : level - 1;
2543                 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
2544                            new_level >= 0 && new_level <= 7) {
2545                         /* new_level set */
2546                 } else
2547                         return -EINVAL;
2548
2549                 brightness_set(new_level);
2550         }
2551
2552         return 0;
2553 }
2554
2555 static struct ibm_struct brightness_driver_data = {
2556         .name = "brightness",
2557         .read = brightness_read,
2558         .write = brightness_write,
2559         .exit = brightness_exit,
2560 };
2561
2562 /*************************************************************************
2563  * Volume subdriver
2564  */
2565
2566 static int volume_read(char *p)
2567 {
2568         int len = 0;
2569         u8 level;
2570
2571         if (!acpi_ec_read(volume_offset, &level)) {
2572                 len += sprintf(p + len, "level:\t\tunreadable\n");
2573         } else {
2574                 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
2575                 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
2576                 len += sprintf(p + len, "commands:\tup, down, mute\n");
2577                 len += sprintf(p + len, "commands:\tlevel <level>"
2578                                " (<level> is 0-15)\n");
2579         }
2580
2581         return len;
2582 }
2583
2584 static int volume_write(char *buf)
2585 {
2586         int cmos_cmd, inc, i;
2587         u8 level, mute;
2588         int new_level, new_mute;
2589         char *cmd;
2590
2591         while ((cmd = next_cmd(&buf))) {
2592                 if (!acpi_ec_read(volume_offset, &level))
2593                         return -EIO;
2594                 new_mute = mute = level & 0x40;
2595                 new_level = level = level & 0xf;
2596
2597                 if (strlencmp(cmd, "up") == 0) {
2598                         if (mute)
2599                                 new_mute = 0;
2600                         else
2601                                 new_level = level == 15 ? 15 : level + 1;
2602                 } else if (strlencmp(cmd, "down") == 0) {
2603                         if (mute)
2604                                 new_mute = 0;
2605                         else
2606                                 new_level = level == 0 ? 0 : level - 1;
2607                 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
2608                            new_level >= 0 && new_level <= 15) {
2609                         /* new_level set */
2610                 } else if (strlencmp(cmd, "mute") == 0) {
2611                         new_mute = 0x40;
2612                 } else
2613                         return -EINVAL;
2614
2615                 if (new_level != level) {       /* mute doesn't change */
2616                         cmos_cmd = new_level > level ? TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN;
2617                         inc = new_level > level ? 1 : -1;
2618
2619                         if (mute && (issue_thinkpad_cmos_command(cmos_cmd) ||
2620                                      !acpi_ec_write(volume_offset, level)))
2621                                 return -EIO;
2622
2623                         for (i = level; i != new_level; i += inc)
2624                                 if (issue_thinkpad_cmos_command(cmos_cmd) ||
2625                                     !acpi_ec_write(volume_offset, i + inc))
2626                                         return -EIO;
2627
2628                         if (mute && (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) ||
2629                                      !acpi_ec_write(volume_offset,
2630                                                     new_level + mute)))
2631                                 return -EIO;
2632                 }
2633
2634                 if (new_mute != mute) { /* level doesn't change */
2635                         cmos_cmd = new_mute ? TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP;
2636
2637                         if (issue_thinkpad_cmos_command(cmos_cmd) ||
2638                             !acpi_ec_write(volume_offset, level + new_mute))
2639                                 return -EIO;
2640                 }
2641         }
2642
2643         return 0;
2644 }
2645
2646 static struct ibm_struct volume_driver_data = {
2647         .name = "volume",
2648         .read = volume_read,
2649         .write = volume_write,
2650 };
2651
2652 /*************************************************************************
2653  * Fan subdriver
2654  */
2655
2656 /*
2657  * FAN ACCESS MODES
2658  *
2659  * TPACPI_FAN_RD_ACPI_GFAN:
2660  *      ACPI GFAN method: returns fan level
2661  *
2662  *      see TPACPI_FAN_WR_ACPI_SFAN
2663  *      EC 0x2f (HFSP) not available if GFAN exists
2664  *
2665  * TPACPI_FAN_WR_ACPI_SFAN:
2666  *      ACPI SFAN method: sets fan level, 0 (stop) to 7 (max)
2667  *
2668  *      EC 0x2f (HFSP) might be available *for reading*, but do not use
2669  *      it for writing.
2670  *
2671  * TPACPI_FAN_WR_TPEC:
2672  *      ThinkPad EC register 0x2f (HFSP): fan control loop mode
2673  *      Supported on almost all ThinkPads
2674  *
2675  *      Fan speed changes of any sort (including those caused by the
2676  *      disengaged mode) are usually done slowly by the firmware as the
2677  *      maximum ammount of fan duty cycle change per second seems to be
2678  *      limited.
2679  *
2680  *      Reading is not available if GFAN exists.
2681  *      Writing is not available if SFAN exists.
2682  *
2683  *      Bits
2684  *       7      automatic mode engaged;
2685  *              (default operation mode of the ThinkPad)
2686  *              fan level is ignored in this mode.
2687  *       6      full speed mode (takes precedence over bit 7);
2688  *              not available on all thinkpads.  May disable
2689  *              the tachometer while the fan controller ramps up
2690  *              the speed (which can take up to a few *minutes*).
2691  *              Speeds up fan to 100% duty-cycle, which is far above
2692  *              the standard RPM levels.  It is not impossible that
2693  *              it could cause hardware damage.
2694  *      5-3     unused in some models.  Extra bits for fan level
2695  *              in others, but still useless as all values above
2696  *              7 map to the same speed as level 7 in these models.
2697  *      2-0     fan level (0..7 usually)
2698  *                      0x00 = stop
2699  *                      0x07 = max (set when temperatures critical)
2700  *              Some ThinkPads may have other levels, see
2701  *              TPACPI_FAN_WR_ACPI_FANS (X31/X40/X41)
2702  *
2703  *      FIRMWARE BUG: on some models, EC 0x2f might not be initialized at
2704  *      boot. Apparently the EC does not intialize it, so unless ACPI DSDT
2705  *      does so, its initial value is meaningless (0x07).
2706  *
2707  *      For firmware bugs, refer to:
2708  *      http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
2709  *
2710  *      ----
2711  *
2712  *      ThinkPad EC register 0x84 (LSB), 0x85 (MSB):
2713  *      Main fan tachometer reading (in RPM)
2714  *
2715  *      This register is present on all ThinkPads with a new-style EC, and
2716  *      it is known not to be present on the A21m/e, and T22, as there is
2717  *      something else in offset 0x84 according to the ACPI DSDT.  Other
2718  *      ThinkPads from this same time period (and earlier) probably lack the
2719  *      tachometer as well.
2720  *
2721  *      Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare
2722  *      was never fixed by IBM to report the EC firmware version string
2723  *      probably support the tachometer (like the early X models), so
2724  *      detecting it is quite hard.  We need more data to know for sure.
2725  *
2726  *      FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings
2727  *      might result.
2728  *
2729  *      FIRMWARE BUG: may go stale while the EC is switching to full speed
2730  *      mode.
2731  *
2732  *      For firmware bugs, refer to:
2733  *      http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
2734  *
2735  * TPACPI_FAN_WR_ACPI_FANS:
2736  *      ThinkPad X31, X40, X41.  Not available in the X60.
2737  *
2738  *      FANS ACPI handle: takes three arguments: low speed, medium speed,
2739  *      high speed.  ACPI DSDT seems to map these three speeds to levels
2740  *      as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH
2741  *      (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3")
2742  *
2743  *      The speeds are stored on handles
2744  *      (FANA:FAN9), (FANC:FANB), (FANE:FAND).
2745  *
2746  *      There are three default speed sets, acessible as handles:
2747  *      FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
2748  *
2749  *      ACPI DSDT switches which set is in use depending on various
2750  *      factors.
2751  *
2752  *      TPACPI_FAN_WR_TPEC is also available and should be used to
2753  *      command the fan.  The X31/X40/X41 seems to have 8 fan levels,
2754  *      but the ACPI tables just mention level 7.
2755  */
2756
2757 static enum fan_status_access_mode fan_status_access_mode;
2758 static enum fan_control_access_mode fan_control_access_mode;
2759 static enum fan_control_commands fan_control_commands;
2760
2761 static u8 fan_control_initial_status;
2762 static u8 fan_control_desired_level;
2763
2764 static void fan_watchdog_fire(struct work_struct *ignored);
2765 static int fan_watchdog_maxinterval;
2766 static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
2767
2768 IBM_HANDLE(fans, ec, "FANS");   /* X31, X40, X41 */
2769 IBM_HANDLE(gfan, ec, "GFAN",    /* 570 */
2770            "\\FSPD",            /* 600e/x, 770e, 770x */
2771            );                   /* all others */
2772 IBM_HANDLE(sfan, ec, "SFAN",    /* 570 */
2773            "JFNS",              /* 770x-JL */
2774            );                   /* all others */
2775
2776 /*
2777  * SYSFS fan layout: hwmon compatible (device)
2778  *
2779  * pwm*_enable:
2780  *      0: "disengaged" mode
2781  *      1: manual mode
2782  *      2: native EC "auto" mode (recommended, hardware default)
2783  *
2784  * pwm*: set speed in manual mode, ignored otherwise.
2785  *      0 is level 0; 255 is level 7. Intermediate points done with linear
2786  *      interpolation.
2787  *
2788  * fan*_input: tachometer reading, RPM
2789  *
2790  *
2791  * SYSFS fan layout: extensions
2792  *
2793  * fan_watchdog (driver):
2794  *      fan watchdog interval in seconds, 0 disables (default), max 120
2795  */
2796
2797 /* sysfs fan pwm1_enable ----------------------------------------------- */
2798 static ssize_t fan_pwm1_enable_show(struct device *dev,
2799                                     struct device_attribute *attr,
2800                                     char *buf)
2801 {
2802         int res, mode;
2803         u8 status;
2804
2805         res = fan_get_status_safe(&status);
2806         if (res)
2807                 return res;
2808
2809         if (unlikely(tp_features.fan_ctrl_status_undef)) {
2810                 if (status != fan_control_initial_status) {
2811                         tp_features.fan_ctrl_status_undef = 0;
2812                 } else {
2813                         /* Return most likely status. In fact, it
2814                          * might be the only possible status */
2815                         status = TP_EC_FAN_AUTO;
2816                 }
2817         }
2818
2819         if (status & TP_EC_FAN_FULLSPEED) {
2820                 mode = 0;
2821         } else if (status & TP_EC_FAN_AUTO) {
2822                 mode = 2;
2823         } else
2824                 mode = 1;
2825
2826         return snprintf(buf, PAGE_SIZE, "%d\n", mode);
2827 }
2828
2829 static ssize_t fan_pwm1_enable_store(struct device *dev,
2830                                      struct device_attribute *attr,
2831                                      const char *buf, size_t count)
2832 {
2833         unsigned long t;
2834         int res, level;
2835
2836         if (parse_strtoul(buf, 2, &t))
2837                 return -EINVAL;
2838
2839         switch (t) {
2840         case 0:
2841                 level = TP_EC_FAN_FULLSPEED;
2842                 break;
2843         case 1:
2844                 level = TPACPI_FAN_LAST_LEVEL;
2845                 break;
2846         case 2:
2847                 level = TP_EC_FAN_AUTO;
2848                 break;
2849         case 3:
2850                 /* reserved for software-controlled auto mode */
2851                 return -ENOSYS;
2852         default:
2853                 return -EINVAL;
2854         }
2855
2856         res = fan_set_level_safe(level);
2857         if (res == -ENXIO)
2858                 return -EINVAL;
2859         else if (res < 0)
2860                 return res;
2861
2862         fan_watchdog_reset();
2863
2864         return count;
2865 }
2866
2867 static struct device_attribute dev_attr_fan_pwm1_enable =
2868         __ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
2869                 fan_pwm1_enable_show, fan_pwm1_enable_store);
2870
2871 /* sysfs fan pwm1 ------------------------------------------------------ */
2872 static ssize_t fan_pwm1_show(struct device *dev,
2873                              struct device_attribute *attr,
2874                              char *buf)
2875 {
2876         int res;
2877         u8 status;
2878
2879         res = fan_get_status_safe(&status);
2880         if (res)
2881                 return res;
2882
2883         if (unlikely(tp_features.fan_ctrl_status_undef)) {
2884                 if (status != fan_control_initial_status) {
2885                         tp_features.fan_ctrl_status_undef = 0;
2886                 } else {
2887                         status = TP_EC_FAN_AUTO;
2888                 }
2889         }
2890
2891         if ((status &
2892              (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0)
2893                 status = fan_control_desired_level;
2894
2895         if (status > 7)
2896                 status = 7;
2897
2898         return snprintf(buf, PAGE_SIZE, "%u\n", (status * 255) / 7);
2899 }
2900
2901 static ssize_t fan_pwm1_store(struct device *dev,
2902                               struct device_attribute *attr,
2903                               const char *buf, size_t count)
2904 {
2905         unsigned long s;
2906         int rc;
2907         u8 status, newlevel;
2908
2909         if (parse_strtoul(buf, 255, &s))
2910                 return -EINVAL;
2911
2912         /* scale down from 0-255 to 0-7 */
2913         newlevel = (s >> 5) & 0x07;
2914
2915         rc = mutex_lock_interruptible(&fan_mutex);
2916         if (rc < 0)
2917                 return rc;
2918
2919         rc = fan_get_status(&status);
2920         if (!rc && (status &
2921                     (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
2922                 rc = fan_set_level(newlevel);
2923                 if (rc == -ENXIO)
2924                         rc = -EINVAL;
2925                 else if (!rc) {
2926                         fan_update_desired_level(newlevel);
2927                         fan_watchdog_reset();
2928                 }
2929         }
2930
2931         mutex_unlock(&fan_mutex);
2932         return (rc)? rc : count;
2933 }
2934
2935 static struct device_attribute dev_attr_fan_pwm1 =
2936         __ATTR(pwm1, S_IWUSR | S_IRUGO,
2937                 fan_pwm1_show, fan_pwm1_store);
2938
2939 /* sysfs fan fan1_input ------------------------------------------------ */
2940 static ssize_t fan_fan1_input_show(struct device *dev,
2941                            struct device_attribute *attr,
2942                            char *buf)
2943 {
2944         int res;
2945         unsigned int speed;
2946
2947         res = fan_get_speed(&speed);
2948         if (res < 0)
2949                 return res;
2950
2951         return snprintf(buf, PAGE_SIZE, "%u\n", speed);
2952 }
2953
2954 static struct device_attribute dev_attr_fan_fan1_input =
2955         __ATTR(fan1_input, S_IRUGO,
2956                 fan_fan1_input_show, NULL);
2957
2958 /* sysfs fan fan_watchdog (driver) ------------------------------------- */
2959 static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
2960                                      char *buf)
2961 {
2962         return snprintf(buf, PAGE_SIZE, "%u\n", fan_watchdog_maxinterval);
2963 }
2964
2965 static ssize_t fan_fan_watchdog_store(struct device_driver *drv,
2966                                       const char *buf, size_t count)
2967 {
2968         unsigned long t;
2969
2970         if (parse_strtoul(buf, 120, &t))
2971                 return -EINVAL;
2972
2973         if (!fan_control_allowed)
2974                 return -EPERM;
2975
2976         fan_watchdog_maxinterval = t;
2977         fan_watchdog_reset();
2978
2979         return count;
2980 }
2981
2982 static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO,
2983                 fan_fan_watchdog_show, fan_fan_watchdog_store);
2984
2985 /* --------------------------------------------------------------------- */
2986 static struct attribute *fan_attributes[] = {
2987         &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr,
2988         &dev_attr_fan_fan1_input.attr,
2989         NULL
2990 };
2991
2992 static const struct attribute_group fan_attr_group = {
2993         .attrs = fan_attributes,
2994 };
2995
2996 static int __init fan_init(struct ibm_init_struct *iibm)
2997 {
2998         int rc;
2999
3000         vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n");
3001
3002         mutex_init(&fan_mutex);
3003         fan_status_access_mode = TPACPI_FAN_NONE;
3004         fan_control_access_mode = TPACPI_FAN_WR_NONE;
3005         fan_control_commands = 0;
3006         fan_watchdog_maxinterval = 0;
3007         tp_features.fan_ctrl_status_undef = 0;
3008         fan_control_desired_level = 7;
3009
3010         IBM_ACPIHANDLE_INIT(fans);
3011         IBM_ACPIHANDLE_INIT(gfan);
3012         IBM_ACPIHANDLE_INIT(sfan);
3013
3014         if (gfan_handle) {
3015                 /* 570, 600e/x, 770e, 770x */
3016                 fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
3017         } else {
3018                 /* all other ThinkPads: note that even old-style
3019                  * ThinkPad ECs supports the fan control register */
3020                 if (likely(acpi_ec_read(fan_status_offset,
3021                                         &fan_control_initial_status))) {
3022                         fan_status_access_mode = TPACPI_FAN_RD_TPEC;
3023
3024                         /* In some ThinkPads, neither the EC nor the ACPI
3025                          * DSDT initialize the fan status, and it ends up
3026                          * being set to 0x07 when it *could* be either
3027                          * 0x07 or 0x80.
3028                          *
3029                          * Enable for TP-1Y (T43), TP-78 (R51e),
3030                          * TP-76 (R52), TP-70 (T43, R52), which are known
3031                          * to be buggy. */
3032                         if (fan_control_initial_status == 0x07 &&
3033                             ibm_thinkpad_ec_found &&
3034                             ((ibm_thinkpad_ec_found[0] == '1' &&
3035                               ibm_thinkpad_ec_found[1] == 'Y') ||
3036                              (ibm_thinkpad_ec_found[0] == '7' &&
3037                               (ibm_thinkpad_ec_found[1] == '6' ||
3038                                ibm_thinkpad_ec_found[1] == '8' ||
3039                                ibm_thinkpad_ec_found[1] == '0'))
3040                             )) {
3041                                 printk(IBM_NOTICE
3042                                        "fan_init: initial fan status is "
3043                                        "unknown, assuming it is in auto "
3044                                        "mode\n");
3045                                 tp_features.fan_ctrl_status_undef = 1;
3046                         }
3047                 } else {
3048                         printk(IBM_ERR
3049                                "ThinkPad ACPI EC access misbehaving, "
3050                                "fan status and control unavailable\n");
3051                         return 1;
3052                 }
3053         }
3054
3055         if (sfan_handle) {
3056                 /* 570, 770x-JL */
3057                 fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN;
3058                 fan_control_commands |=
3059                     TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_ENABLE;
3060         } else {
3061                 if (!gfan_handle) {
3062                         /* gfan without sfan means no fan control */
3063                         /* all other models implement TP EC 0x2f control */
3064
3065                         if (fans_handle) {
3066                                 /* X31, X40, X41 */
3067                                 fan_control_access_mode =
3068                                     TPACPI_FAN_WR_ACPI_FANS;
3069                                 fan_control_commands |=
3070                                     TPACPI_FAN_CMD_SPEED |
3071                                     TPACPI_FAN_CMD_LEVEL |
3072                                     TPACPI_FAN_CMD_ENABLE;
3073                         } else {
3074                                 fan_control_access_mode = TPACPI_FAN_WR_TPEC;
3075                                 fan_control_commands |=
3076                                     TPACPI_FAN_CMD_LEVEL |
3077                                     TPACPI_FAN_CMD_ENABLE;
3078                         }
3079                 }
3080         }
3081
3082         vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n",
3083                 str_supported(fan_status_access_mode != TPACPI_FAN_NONE ||
3084                   fan_control_access_mode != TPACPI_FAN_WR_NONE),
3085                 fan_status_access_mode, fan_control_access_mode);
3086
3087         /* fan control master switch */
3088         if (!fan_control_allowed) {
3089                 fan_control_access_mode = TPACPI_FAN_WR_NONE;
3090                 fan_control_commands = 0;
3091                 dbg_printk(TPACPI_DBG_INIT,
3092                            "fan control features disabled by parameter\n");
3093         }
3094
3095         /* update fan_control_desired_level */
3096         if (fan_status_access_mode != TPACPI_FAN_NONE)
3097                 fan_get_status_safe(NULL);
3098
3099         if (fan_status_access_mode != TPACPI_FAN_NONE ||
3100             fan_control_access_mode != TPACPI_FAN_WR_NONE) {
3101                 rc = sysfs_create_group(&tpacpi_pdev->dev.kobj,
3102                                          &fan_attr_group);
3103                 if (!(rc < 0))
3104                         rc = driver_create_file(&tpacpi_pdriver.driver,
3105                                         &driver_attr_fan_watchdog);
3106                 if (rc < 0)
3107                         return rc;
3108                 return 0;
3109         } else
3110                 return 1;
3111 }
3112
3113 /*
3114  * Call with fan_mutex held
3115  */
3116 static void fan_update_desired_level(u8 status)
3117 {
3118         if ((status &
3119              (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
3120                 if (status > 7)
3121                         fan_control_desired_level = 7;
3122                 else
3123                         fan_control_desired_level = status;
3124         }
3125 }
3126
3127 static int fan_get_status(u8 *status)
3128 {
3129         u8 s;
3130
3131         /* TODO:
3132          * Add TPACPI_FAN_RD_ACPI_FANS ? */
3133
3134         switch (fan_status_access_mode) {
3135         case TPACPI_FAN_RD_ACPI_GFAN:
3136                 /* 570, 600e/x, 770e, 770x */
3137
3138                 if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
3139                         return -EIO;
3140
3141                 if (likely(status))
3142                         *status = s & 0x07;
3143
3144                 break;
3145
3146         case TPACPI_FAN_RD_TPEC:
3147                 /* all except 570, 600e/x, 770e, 770x */
3148                 if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
3149                         return -EIO;
3150
3151                 if (likely(status))
3152                         *status = s;
3153
3154                 break;
3155
3156         default:
3157                 return -ENXIO;
3158         }
3159
3160         return 0;
3161 }
3162
3163 static int fan_get_status_safe(u8 *status)
3164 {
3165         int rc;
3166         u8 s;
3167
3168         rc = mutex_lock_interruptible(&fan_mutex);
3169         if (rc < 0)
3170                 return rc;
3171         rc = fan_get_status(&s);
3172         if (!rc)
3173                 fan_update_desired_level(s);
3174         mutex_unlock(&fan_mutex);
3175
3176         if (status)
3177                 *status = s;
3178
3179         return rc;
3180 }
3181
3182 static void fan_exit(void)
3183 {
3184         vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n");
3185
3186         /* FIXME: can we really do this unconditionally? */
3187         sysfs_remove_group(&tpacpi_pdev->dev.kobj, &fan_attr_group);
3188         driver_remove_file(&tpacpi_pdriver.driver, &driver_attr_fan_watchdog);
3189
3190         cancel_delayed_work(&fan_watchdog_task);
3191         flush_scheduled_work();
3192 }
3193
3194 static int fan_get_speed(unsigned int *speed)
3195 {
3196         u8 hi, lo;
3197
3198         switch (fan_status_access_mode) {
3199         case TPACPI_FAN_RD_TPEC:
3200                 /* all except 570, 600e/x, 770e, 770x */
3201                 if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
3202                              !acpi_ec_read(fan_rpm_offset + 1, &hi)))
3203                         return -EIO;
3204
3205                 if (likely(speed))
3206                         *speed = (hi << 8) | lo;
3207
3208                 break;
3209
3210         default:
3211                 return -ENXIO;
3212         }
3213
3214         return 0;
3215 }
3216
3217 static void fan_watchdog_fire(struct work_struct *ignored)
3218 {
3219         int rc;
3220
3221         printk(IBM_NOTICE "fan watchdog: enabling fan\n");
3222         rc = fan_set_enable();
3223         if (rc < 0) {
3224                 printk(IBM_ERR "fan watchdog: error %d while enabling fan, "
3225                         "will try again later...\n", -rc);
3226                 /* reschedule for later */
3227                 fan_watchdog_reset();
3228         }
3229 }
3230
3231 static void fan_watchdog_reset(void)
3232 {
3233         static int fan_watchdog_active = 0;
3234
3235         if (fan_control_access_mode == TPACPI_FAN_WR_NONE)
3236                 return;
3237
3238         if (fan_watchdog_active)
3239                 cancel_delayed_work(&fan_watchdog_task);
3240
3241         if (fan_watchdog_maxinterval > 0) {
3242                 fan_watchdog_active = 1;
3243                 if (!schedule_delayed_work(&fan_watchdog_task,
3244                                 msecs_to_jiffies(fan_watchdog_maxinterval
3245                                                  * 1000))) {
3246                         printk(IBM_ERR "failed to schedule the fan watchdog, "
3247                                "watchdog will not trigger\n");
3248                 }
3249         } else
3250                 fan_watchdog_active = 0;
3251 }
3252
3253 static int fan_set_level(int level)
3254 {
3255         if (!fan_control_allowed)
3256                 return -EPERM;
3257
3258         switch (fan_control_access_mode) {
3259         case TPACPI_FAN_WR_ACPI_SFAN:
3260                 if (level >= 0 && level <= 7) {
3261                         if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
3262                                 return -EIO;
3263                 } else
3264                         return -EINVAL;
3265                 break;
3266
3267         case TPACPI_FAN_WR_ACPI_FANS:
3268         case TPACPI_FAN_WR_TPEC:
3269                 if ((level != TP_EC_FAN_AUTO) &&
3270                     (level != TP_EC_FAN_FULLSPEED) &&
3271                     ((level < 0) || (level > 7)))
3272                         return -EINVAL;
3273
3274                 /* safety net should the EC not support AUTO
3275                  * or FULLSPEED mode bits and just ignore them */
3276                 if (level & TP_EC_FAN_FULLSPEED)
3277                         level |= 7;     /* safety min speed 7 */
3278                 else if (level & TP_EC_FAN_FULLSPEED)
3279                         level |= 4;     /* safety min speed 4 */
3280
3281                 if (!acpi_ec_write(fan_status_offset, level))
3282                         return -EIO;
3283                 else
3284                         tp_features.fan_ctrl_status_undef = 0;
3285                 break;
3286
3287         default:
3288                 return -ENXIO;
3289         }
3290         return 0;
3291 }
3292
3293 static int fan_set_level_safe(int level)
3294 {
3295         int rc;
3296
3297         if (!fan_control_allowed)
3298                 return -EPERM;
3299
3300         rc = mutex_lock_interruptible(&fan_mutex);
3301         if (rc < 0)
3302                 return rc;
3303
3304         if (level == TPACPI_FAN_LAST_LEVEL)
3305                 level = fan_control_desired_level;
3306
3307         rc = fan_set_level(level);
3308         if (!rc)
3309                 fan_update_desired_level(level);
3310
3311         mutex_unlock(&fan_mutex);
3312         return rc;
3313 }
3314
3315 static int fan_set_enable(void)
3316 {
3317         u8 s;
3318         int rc;
3319
3320         if (!fan_control_allowed)
3321                 return -EPERM;
3322
3323         rc = mutex_lock_interruptible(&fan_mutex);
3324         if (rc < 0)
3325                 return rc;
3326
3327         switch (fan_control_access_mode) {
3328         case TPACPI_FAN_WR_ACPI_FANS:
3329         case TPACPI_FAN_WR_TPEC:
3330                 rc = fan_get_status(&s);
3331                 if (rc < 0)
3332                         break;
3333
3334                 /* Don't go out of emergency fan mode */
3335                 if (s != 7) {
3336                         s &= 0x07;
3337                         s |= TP_EC_FAN_AUTO | 4; /* min fan speed 4 */
3338                 }
3339
3340                 if (!acpi_ec_write(fan_status_offset, s))
3341                         rc = -EIO;
3342                 else {
3343                         tp_features.fan_ctrl_status_undef = 0;
3344                         rc = 0;
3345                 }
3346                 break;
3347
3348         case TPACPI_FAN_WR_ACPI_SFAN:
3349                 rc = fan_get_status(&s);
3350                 if (rc < 0)
3351                         break;
3352
3353                 s &= 0x07;
3354
3355                 /* Set fan to at least level 4 */
3356                 s |= 4;
3357
3358                 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
3359                         rc= -EIO;
3360                 else
3361                         rc = 0;
3362                 break;
3363
3364         default:
3365                 rc = -ENXIO;
3366         }
3367
3368         mutex_unlock(&fan_mutex);
3369         return rc;
3370 }
3371
3372 static int fan_set_disable(void)
3373 {
3374         int rc;
3375
3376         if (!fan_control_allowed)
3377                 return -EPERM;
3378
3379         rc = mutex_lock_interruptible(&fan_mutex);
3380         if (rc < 0)
3381                 return rc;
3382
3383         rc = 0;
3384         switch (fan_control_access_mode) {
3385         case TPACPI_FAN_WR_ACPI_FANS:
3386         case TPACPI_FAN_WR_TPEC:
3387                 if (!acpi_ec_write(fan_status_offset, 0x00))
3388                         rc = -EIO;
3389                 else {
3390                         fan_control_desired_level = 0;
3391                         tp_features.fan_ctrl_status_undef = 0;
3392                 }
3393                 break;
3394
3395         case TPACPI_FAN_WR_ACPI_SFAN:
3396                 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
3397                         rc = -EIO;
3398                 else
3399                         fan_control_desired_level = 0;
3400                 break;
3401
3402         default:
3403                 rc = -ENXIO;
3404         }
3405
3406
3407         mutex_unlock(&fan_mutex);
3408         return rc;
3409 }
3410
3411 static int fan_set_speed(int speed)
3412 {
3413         int rc;
3414
3415         if (!fan_control_allowed)
3416                 return -EPERM;
3417
3418         rc = mutex_lock_interruptible(&fan_mutex);
3419         if (rc < 0)
3420                 return rc;
3421
3422         rc = 0;
3423         switch (fan_control_access_mode) {
3424         case TPACPI_FAN_WR_ACPI_FANS:
3425                 if (speed >= 0 && speed <= 65535) {
3426                         if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
3427                                         speed, speed, speed))
3428                                 rc = -EIO;
3429                 } else
3430                         rc = -EINVAL;
3431                 break;
3432
3433         default:
3434                 rc = -ENXIO;
3435         }
3436
3437         mutex_unlock(&fan_mutex);
3438         return rc;
3439 }
3440
3441 static int fan_read(char *p)
3442 {
3443         int len = 0;
3444         int rc;
3445         u8 status;
3446         unsigned int speed = 0;
3447
3448         switch (fan_status_access_mode) {
3449         case TPACPI_FAN_RD_ACPI_GFAN:
3450                 /* 570, 600e/x, 770e, 770x */
3451                 if ((rc = fan_get_status_safe(&status)) < 0)
3452                         return rc;
3453
3454                 len += sprintf(p + len, "status:\t\t%s\n"
3455                                "level:\t\t%d\n",
3456                                (status != 0) ? "enabled" : "disabled", status);
3457                 break;
3458
3459         case TPACPI_FAN_RD_TPEC:
3460                 /* all except 570, 600e/x, 770e, 770x */
3461                 if ((rc = fan_get_status_safe(&status)) < 0)
3462                         return rc;
3463
3464                 if (unlikely(tp_features.fan_ctrl_status_undef)) {
3465                         if (status != fan_control_initial_status)
3466                                 tp_features.fan_ctrl_status_undef = 0;
3467                         else
3468                                 /* Return most likely status. In fact, it
3469                                  * might be the only possible status */
3470                                 status = TP_EC_FAN_AUTO;
3471                 }
3472
3473                 len += sprintf(p + len, "status:\t\t%s\n",
3474                                (status != 0) ? "enabled" : "disabled");
3475
3476                 if ((rc = fan_get_speed(&speed)) < 0)
3477                         return rc;
3478
3479                 len += sprintf(p + len, "speed:\t\t%d\n", speed);
3480
3481                 if (status & TP_EC_FAN_FULLSPEED)
3482                         /* Disengaged mode takes precedence */
3483                         len += sprintf(p + len, "level:\t\tdisengaged\n");
3484                 else if (status & TP_EC_FAN_AUTO)
3485                         len += sprintf(p + len, "level:\t\tauto\n");
3486                 else
3487                         len += sprintf(p + len, "level:\t\t%d\n", status);
3488                 break;
3489
3490         case TPACPI_FAN_NONE:
3491         default:
3492                 len += sprintf(p + len, "status:\t\tnot supported\n");
3493         }
3494
3495         if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
3496                 len += sprintf(p + len, "commands:\tlevel <level>");
3497
3498                 switch (fan_control_access_mode) {
3499                 case TPACPI_FAN_WR_ACPI_SFAN:
3500                         len += sprintf(p + len, " (<level> is 0-7)\n");
3501                         break;
3502
3503                 default:
3504                         len += sprintf(p + len, " (<level> is 0-7, "
3505                                        "auto, disengaged, full-speed)\n");
3506                         break;
3507                 }
3508         }
3509
3510         if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
3511                 len += sprintf(p + len, "commands:\tenable, disable\n"
3512                                "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
3513                                "1-120 (seconds))\n");
3514
3515         if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
3516                 len += sprintf(p + len, "commands:\tspeed <speed>"
3517                                " (<speed> is 0-65535)\n");
3518
3519         return len;
3520 }
3521
3522 static int fan_write_cmd_level(const char *cmd, int *rc)
3523 {
3524         int level;
3525
3526         if (strlencmp(cmd, "level auto") == 0)
3527                 level = TP_EC_FAN_AUTO;
3528         else if ((strlencmp(cmd, "level disengaged") == 0) |
3529                  (strlencmp(cmd, "level full-speed") == 0))
3530                 level = TP_EC_FAN_FULLSPEED;
3531         else if (sscanf(cmd, "level %d", &level) != 1)
3532                 return 0;
3533
3534         if ((*rc = fan_set_level_safe(level)) == -ENXIO)
3535                 printk(IBM_ERR "level command accepted for unsupported "
3536                        "access mode %d", fan_control_access_mode);
3537
3538         return 1;
3539 }
3540
3541 static int fan_write_cmd_enable(const char *cmd, int *rc)
3542 {
3543         if (strlencmp(cmd, "enable") != 0)
3544                 return 0;
3545
3546         if ((*rc = fan_set_enable()) == -ENXIO)
3547                 printk(IBM_ERR "enable command accepted for unsupported "
3548                        "access mode %d", fan_control_access_mode);
3549
3550         return 1;
3551 }
3552
3553 static int fan_write_cmd_disable(const char *cmd, int *rc)
3554 {
3555         if (strlencmp(cmd, "disable") != 0)
3556                 return 0;
3557
3558         if ((*rc = fan_set_disable()) == -ENXIO)
3559                 printk(IBM_ERR "disable command accepted for unsupported "
3560                        "access mode %d", fan_control_access_mode);
3561
3562         return 1;
3563 }
3564
3565 static int fan_write_cmd_speed(const char *cmd, int *rc)
3566 {
3567         int speed;
3568
3569         /* TODO:
3570          * Support speed <low> <medium> <high> ? */
3571
3572         if (sscanf(cmd, "speed %d", &speed) != 1)
3573                 return 0;
3574
3575         if ((*rc = fan_set_speed(speed)) == -ENXIO)
3576                 printk(IBM_ERR "speed command accepted for unsupported "
3577                        "access mode %d", fan_control_access_mode);
3578
3579         return 1;
3580 }
3581
3582 static int fan_write_cmd_watchdog(const char *cmd, int *rc)
3583 {
3584         int interval;
3585
3586         if (sscanf(cmd, "watchdog %d", &interval) != 1)
3587                 return 0;
3588
3589         if (interval < 0 || interval > 120)
3590                 *rc = -EINVAL;
3591         else
3592                 fan_watchdog_maxinterval = interval;
3593
3594         return 1;
3595 }
3596
3597 static int fan_write(char *buf)
3598 {
3599         char *cmd;
3600         int rc = 0;
3601
3602         while (!rc && (cmd = next_cmd(&buf))) {
3603                 if (!((fan_control_commands & TPACPI_FAN_CMD_LEVEL) &&
3604                       fan_write_cmd_level(cmd, &rc)) &&
3605                     !((fan_control_commands & TPACPI_FAN_CMD_ENABLE) &&
3606                       (fan_write_cmd_enable(cmd, &rc) ||
3607                        fan_write_cmd_disable(cmd, &rc) ||
3608                        fan_write_cmd_watchdog(cmd, &rc))) &&
3609                     !((fan_control_commands & TPACPI_FAN_CMD_SPEED) &&
3610                       fan_write_cmd_speed(cmd, &rc))
3611                     )
3612                         rc = -EINVAL;
3613                 else if (!rc)
3614                         fan_watchdog_reset();
3615         }
3616
3617         return rc;
3618 }
3619
3620 static struct ibm_struct fan_driver_data = {
3621         .name = "fan",
3622         .read = fan_read,
3623         .write = fan_write,
3624         .exit = fan_exit,
3625 };
3626
3627 /****************************************************************************
3628  ****************************************************************************
3629  *
3630  * Infrastructure
3631  *
3632  ****************************************************************************
3633  ****************************************************************************/
3634
3635 /* /proc support */
3636 static struct proc_dir_entry *proc_dir = NULL;
3637
3638 /* Subdriver registry */
3639 static LIST_HEAD(tpacpi_all_drivers);
3640
3641
3642 /*
3643  * Module and infrastructure proble, init and exit handling
3644  */
3645
3646 #ifdef CONFIG_THINKPAD_ACPI_DEBUG
3647 static const char * __init str_supported(int is_supported)
3648 {
3649         static char text_unsupported[] __initdata = "not supported";
3650
3651         return (is_supported)? &text_unsupported[4] : &text_unsupported[0];
3652 }
3653 #endif /* CONFIG_THINKPAD_ACPI_DEBUG */
3654
3655 static int __init ibm_init(struct ibm_init_struct *iibm)
3656 {
3657         int ret;
3658         struct ibm_struct *ibm = iibm->data;
3659         struct proc_dir_entry *entry;
3660
3661         BUG_ON(ibm == NULL);
3662
3663         INIT_LIST_HEAD(&ibm->all_drivers);
3664
3665         if (ibm->flags.experimental && !experimental)
3666                 return 0;
3667
3668         dbg_printk(TPACPI_DBG_INIT,
3669                 "probing for %s\n", ibm->name);
3670
3671         if (iibm->init) {
3672                 ret = iibm->init(iibm);
3673                 if (ret > 0)
3674                         return 0;       /* probe failed */
3675                 if (ret)
3676                         return ret;
3677
3678                 ibm->flags.init_called = 1;
3679         }
3680
3681         if (ibm->acpi) {
3682                 if (ibm->acpi->hid) {
3683                         ret = register_tpacpi_subdriver(ibm);
3684                         if (ret)
3685                                 goto err_out;
3686                 }
3687
3688                 if (ibm->acpi->notify) {
3689                         ret = setup_acpi_notify(ibm);
3690                         if (ret == -ENODEV) {
3691                                 printk(IBM_NOTICE "disabling subdriver %s\n",
3692                                         ibm->name);
3693                                 ret = 0;
3694                                 goto err_out;
3695                         }
3696                         if (ret < 0)
3697                                 goto err_out;
3698                 }
3699         }
3700
3701         dbg_printk(TPACPI_DBG_INIT,
3702                 "%s installed\n", ibm->name);
3703
3704         if (ibm->read) {
3705                 entry = create_proc_entry(ibm->name,
3706                                           S_IFREG | S_IRUGO | S_IWUSR,
3707                                           proc_dir);
3708                 if (!entry) {
3709                         printk(IBM_ERR "unable to create proc entry %s\n",
3710                                ibm->name);
3711                         ret = -ENODEV;
3712                         goto err_out;
3713                 }
3714                 entry->owner = THIS_MODULE;
3715                 entry->data = ibm;
3716                 entry->read_proc = &dispatch_procfs_read;
3717                 if (ibm->write)
3718                         entry->write_proc = &dispatch_procfs_write;
3719                 ibm->flags.proc_created = 1;
3720         }
3721
3722         list_add_tail(&ibm->all_drivers, &tpacpi_all_drivers);
3723
3724         return 0;
3725
3726 err_out:
3727         dbg_printk(TPACPI_DBG_INIT,
3728                 "%s: at error exit path with result %d\n",
3729                 ibm->name, ret);
3730
3731         ibm_exit(ibm);
3732         return (ret < 0)? ret : 0;
3733 }
3734
3735 static void ibm_exit(struct ibm_struct *ibm)
3736 {
3737         dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name);
3738
3739         list_del_init(&ibm->all_drivers);
3740
3741         if (ibm->flags.acpi_notify_installed) {
3742                 dbg_printk(TPACPI_DBG_EXIT,
3743                         "%s: acpi_remove_notify_handler\n", ibm->name);
3744                 BUG_ON(!ibm->acpi);
3745                 acpi_remove_notify_handler(*ibm->acpi->handle,
3746                                            ibm->acpi->type,
3747                                            dispatch_acpi_notify);
3748                 ibm->flags.acpi_notify_installed = 0;
3749                 ibm->flags.acpi_notify_installed = 0;
3750         }
3751
3752         if (ibm->flags.proc_created) {
3753                 dbg_printk(TPACPI_DBG_EXIT,
3754                         "%s: remove_proc_entry\n", ibm->name);
3755                 remove_proc_entry(ibm->name, proc_dir);
3756                 ibm->flags.proc_created = 0;
3757         }
3758
3759         if (ibm->flags.acpi_driver_registered) {
3760                 dbg_printk(TPACPI_DBG_EXIT,
3761                         "%s: acpi_bus_unregister_driver\n", ibm->name);
3762                 BUG_ON(!ibm->acpi);
3763                 acpi_bus_unregister_driver(ibm->acpi->driver);
3764                 kfree(ibm->acpi->driver);
3765                 ibm->acpi->driver = NULL;
3766                 ibm->flags.acpi_driver_registered = 0;
3767         }
3768
3769         if (ibm->flags.init_called && ibm->exit) {
3770                 ibm->exit();
3771                 ibm->flags.init_called = 0;
3772         }
3773
3774         dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name);
3775 }
3776
3777 /* Probing */
3778
3779 static char *ibm_thinkpad_ec_found = NULL;
3780
3781 static char* __init check_dmi_for_ec(void)
3782 {
3783         struct dmi_device *dev = NULL;
3784         char ec_fw_string[18];
3785
3786         /*
3787          * ThinkPad T23 or newer, A31 or newer, R50e or newer,
3788          * X32 or newer, all Z series;  Some models must have an
3789          * up-to-date BIOS or they will not be detected.
3790          *
3791          * See http://thinkwiki.org/wiki/List_of_DMI_IDs
3792          */
3793         while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
3794                 if (sscanf(dev->name,
3795                            "IBM ThinkPad Embedded Controller -[%17c",
3796                            ec_fw_string) == 1) {
3797                         ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
3798                         ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
3799                         return kstrdup(ec_fw_string, GFP_KERNEL);
3800                 }
3801         }
3802         return NULL;
3803 }
3804
3805 static int __init probe_for_thinkpad(void)
3806 {
3807         int is_thinkpad;
3808
3809         if (acpi_disabled)
3810                 return -ENODEV;
3811
3812         /*
3813          * Non-ancient models have better DMI tagging, but very old models
3814          * don't.
3815          */
3816         is_thinkpad = dmi_name_in_vendors("ThinkPad");
3817
3818         /* ec is required because many other handles are relative to it */
3819         IBM_ACPIHANDLE_INIT(ec);
3820         if (!ec_handle) {
3821                 if (is_thinkpad)
3822                         printk(IBM_ERR
3823                                 "Not yet supported ThinkPad detected!\n");
3824                 return -ENODEV;
3825         }
3826
3827         /*
3828          * Risks a regression on very old machines, but reduces potential
3829          * false positives a damn great deal
3830          */
3831         if (!is_thinkpad)
3832                 is_thinkpad = dmi_name_in_vendors("IBM");
3833
3834         if (!is_thinkpad && !force_load)
3835                 return -ENODEV;
3836
3837         return 0;
3838 }
3839
3840
3841 /* Module init, exit, parameters */
3842
3843 static struct ibm_init_struct ibms_init[] __initdata = {
3844         {
3845                 .init = thinkpad_acpi_driver_init,
3846                 .data = &thinkpad_acpi_driver_data,
3847         },
3848         {
3849                 .init = hotkey_init,
3850                 .data = &hotkey_driver_data,
3851         },
3852         {
3853                 .init = bluetooth_init,
3854                 .data = &bluetooth_driver_data,
3855         },
3856         {
3857                 .init = wan_init,
3858                 .data = &wan_driver_data,
3859         },
3860         {
3861                 .init = video_init,
3862                 .data = &video_driver_data,
3863         },
3864         {
3865                 .init = light_init,
3866                 .data = &light_driver_data,
3867         },
3868 #ifdef CONFIG_THINKPAD_ACPI_DOCK
3869         {
3870                 .init = dock_init,
3871                 .data = &dock_driver_data[0],
3872         },
3873         {
3874                 .init = dock_init2,
3875                 .data = &dock_driver_data[1],
3876         },
3877 #endif
3878 #ifdef CONFIG_THINKPAD_ACPI_BAY
3879         {
3880                 .init = bay_init,
3881                 .data = &bay_driver_data,
3882         },
3883 #endif
3884         {
3885                 .init = cmos_init,
3886                 .data = &cmos_driver_data,
3887         },
3888         {
3889                 .init = led_init,
3890                 .data = &led_driver_data,
3891         },
3892         {
3893                 .init = beep_init,
3894                 .data = &beep_driver_data,
3895         },
3896         {
3897                 .init = thermal_init,
3898                 .data = &thermal_driver_data,
3899         },
3900         {
3901                 .data = &ecdump_driver_data,
3902         },
3903         {
3904                 .init = brightness_init,
3905                 .data = &brightness_driver_data,
3906         },
3907         {
3908                 .data = &volume_driver_data,
3909         },
3910         {
3911                 .init = fan_init,
3912                 .data = &fan_driver_data,
3913         },
3914 };
3915
3916 static int __init set_ibm_param(const char *val, struct kernel_param *kp)
3917 {
3918         unsigned int i;
3919         struct ibm_struct *ibm;
3920
3921         for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
3922                 ibm = ibms_init[i].data;
3923                 BUG_ON(ibm == NULL);
3924
3925                 if (strcmp(ibm->name, kp->name) == 0 && ibm->write) {
3926                         if (strlen(val) > sizeof(ibms_init[i].param) - 2)
3927                                 return -ENOSPC;
3928                         strcpy(ibms_init[i].param, val);
3929                         strcat(ibms_init[i].param, ",");
3930                         return 0;
3931                 }
3932         }
3933
3934         return -EINVAL;
3935 }
3936
3937 static int experimental;
3938 module_param(experimental, int, 0);
3939
3940 static u32 dbg_level;
3941 module_param_named(debug, dbg_level, uint, 0);
3942
3943 static int force_load;
3944 module_param(force_load, int, 0);
3945
3946 static int fan_control_allowed;
3947 module_param_named(fan_control, fan_control_allowed, int, 0);
3948
3949 #define IBM_PARAM(feature) \
3950         module_param_call(feature, set_ibm_param, NULL, NULL, 0)
3951
3952 IBM_PARAM(hotkey);
3953 IBM_PARAM(bluetooth);
3954 IBM_PARAM(video);
3955 IBM_PARAM(light);
3956 #ifdef CONFIG_THINKPAD_ACPI_DOCK
3957 IBM_PARAM(dock);
3958 #endif
3959 #ifdef CONFIG_THINKPAD_ACPI_BAY
3960 IBM_PARAM(bay);
3961 #endif /* CONFIG_THINKPAD_ACPI_BAY */
3962 IBM_PARAM(cmos);
3963 IBM_PARAM(led);
3964 IBM_PARAM(beep);
3965 IBM_PARAM(ecdump);
3966 IBM_PARAM(brightness);
3967 IBM_PARAM(volume);
3968 IBM_PARAM(fan);
3969
3970 static int __init thinkpad_acpi_module_init(void)
3971 {
3972         int ret, i;
3973
3974         /* Driver-level probe */
3975         ret = probe_for_thinkpad();
3976         if (ret)
3977                 return ret;
3978
3979         /* Driver initialization */
3980         ibm_thinkpad_ec_found = check_dmi_for_ec();
3981         IBM_ACPIHANDLE_INIT(ecrd);
3982         IBM_ACPIHANDLE_INIT(ecwr);
3983
3984         proc_dir = proc_mkdir(IBM_PROC_DIR, acpi_root_dir);
3985         if (!proc_dir) {
3986                 printk(IBM_ERR "unable to create proc dir " IBM_PROC_DIR);
3987                 thinkpad_acpi_module_exit();
3988                 return -ENODEV;
3989         }
3990         proc_dir->owner = THIS_MODULE;
3991
3992         ret = platform_driver_register(&tpacpi_pdriver);
3993         if (ret) {
3994                 printk(IBM_ERR "unable to register platform driver\n");
3995                 thinkpad_acpi_module_exit();
3996                 return ret;
3997         }
3998         ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
3999         if (ret) {
4000                 printk(IBM_ERR "unable to create sysfs driver attributes\n");
4001                 thinkpad_acpi_module_exit();
4002                 return ret;
4003         }
4004
4005
4006         /* Device initialization */
4007         tpacpi_pdev = platform_device_register_simple(IBM_DRVR_NAME, -1,
4008                                                         NULL, 0);
4009         if (IS_ERR(tpacpi_pdev)) {
4010                 ret = PTR_ERR(tpacpi_pdev);
4011                 tpacpi_pdev = NULL;
4012                 printk(IBM_ERR "unable to register platform device\n");
4013                 thinkpad_acpi_module_exit();
4014                 return ret;
4015         }
4016         tpacpi_hwmon = hwmon_device_register(&tpacpi_pdev->dev);
4017         if (IS_ERR(tpacpi_hwmon)) {
4018                 ret = PTR_ERR(tpacpi_hwmon);
4019                 tpacpi_hwmon = NULL;
4020                 printk(IBM_ERR "unable to register hwmon device\n");
4021                 thinkpad_acpi_module_exit();
4022                 return ret;
4023         }
4024         for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
4025                 ret = ibm_init(&ibms_init[i]);
4026                 if (ret >= 0 && *ibms_init[i].param)
4027                         ret = ibms_init[i].data->write(ibms_init[i].param);
4028                 if (ret < 0) {
4029                         thinkpad_acpi_module_exit();
4030                         return ret;
4031                 }
4032         }
4033
4034         return 0;
4035 }
4036
4037 static void thinkpad_acpi_module_exit(void)
4038 {
4039         struct ibm_struct *ibm, *itmp;
4040
4041         list_for_each_entry_safe_reverse(ibm, itmp,
4042                                          &tpacpi_all_drivers,
4043                                          all_drivers) {
4044                 ibm_exit(ibm);
4045         }
4046
4047         dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
4048
4049         if (tpacpi_hwmon)
4050                 hwmon_device_unregister(tpacpi_hwmon);
4051
4052         if (tpacpi_pdev)
4053                 platform_device_unregister(tpacpi_pdev);
4054
4055         tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
4056         platform_driver_unregister(&tpacpi_pdriver);
4057
4058         if (proc_dir)
4059                 remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
4060
4061         kfree(ibm_thinkpad_ec_found);
4062 }
4063
4064 module_init(thinkpad_acpi_module_init);
4065 module_exit(thinkpad_acpi_module_exit);