1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#define TPACPI_VERSION "0.23"
25#define TPACPI_SYSFS_VERSION 0x020500
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50#include <linux/kernel.h>
51#include <linux/module.h>
52#include <linux/init.h>
53#include <linux/types.h>
54#include <linux/string.h>
55#include <linux/list.h>
56#include <linux/mutex.h>
57#include <linux/sched.h>
58#include <linux/kthread.h>
59#include <linux/freezer.h>
60#include <linux/delay.h>
61
62#include <linux/nvram.h>
63#include <linux/proc_fs.h>
64#include <linux/sysfs.h>
65#include <linux/backlight.h>
66#include <linux/fb.h>
67#include <linux/platform_device.h>
68#include <linux/hwmon.h>
69#include <linux/hwmon-sysfs.h>
70#include <linux/input.h>
71#include <linux/leds.h>
72#include <linux/rfkill.h>
73#include <asm/uaccess.h>
74
75#include <linux/dmi.h>
76#include <linux/jiffies.h>
77#include <linux/workqueue.h>
78
79#include <acpi/acpi_drivers.h>
80
81#include <linux/pci_ids.h>
82
83
84
85#define TP_CMOS_VOLUME_DOWN 0
86#define TP_CMOS_VOLUME_UP 1
87#define TP_CMOS_VOLUME_MUTE 2
88#define TP_CMOS_BRIGHTNESS_UP 4
89#define TP_CMOS_BRIGHTNESS_DOWN 5
90#define TP_CMOS_THINKLIGHT_ON 12
91#define TP_CMOS_THINKLIGHT_OFF 13
92
93
94enum tp_nvram_addr {
95 TP_NVRAM_ADDR_HK2 = 0x57,
96 TP_NVRAM_ADDR_THINKLIGHT = 0x58,
97 TP_NVRAM_ADDR_VIDEO = 0x59,
98 TP_NVRAM_ADDR_BRIGHTNESS = 0x5e,
99 TP_NVRAM_ADDR_MIXER = 0x60,
100};
101
102
103enum {
104 TP_NVRAM_MASK_HKT_THINKPAD = 0x08,
105 TP_NVRAM_MASK_HKT_ZOOM = 0x20,
106 TP_NVRAM_MASK_HKT_DISPLAY = 0x40,
107 TP_NVRAM_MASK_HKT_HIBERNATE = 0x80,
108 TP_NVRAM_MASK_THINKLIGHT = 0x10,
109 TP_NVRAM_MASK_HKT_DISPEXPND = 0x30,
110 TP_NVRAM_MASK_HKT_BRIGHTNESS = 0x20,
111 TP_NVRAM_MASK_LEVEL_BRIGHTNESS = 0x0f,
112 TP_NVRAM_POS_LEVEL_BRIGHTNESS = 0,
113 TP_NVRAM_MASK_MUTE = 0x40,
114 TP_NVRAM_MASK_HKT_VOLUME = 0x80,
115 TP_NVRAM_MASK_LEVEL_VOLUME = 0x0f,
116 TP_NVRAM_POS_LEVEL_VOLUME = 0,
117};
118
119
120#define TPACPI_ACPI_HKEY_HID "IBM0068"
121
122
123#define TPACPI_HKEY_INPUT_PRODUCT 0x5054
124#define TPACPI_HKEY_INPUT_VERSION 0x4101
125
126
127enum {
128 TP_ACPI_WGSV_GET_STATE = 0x01,
129 TP_ACPI_WGSV_PWR_ON_ON_RESUME = 0x02,
130 TP_ACPI_WGSV_PWR_OFF_ON_RESUME = 0x03,
131 TP_ACPI_WGSV_SAVE_STATE = 0x04,
132};
133
134
135enum {
136 TP_ACPI_WGSV_STATE_WWANEXIST = 0x0001,
137 TP_ACPI_WGSV_STATE_WWANPWR = 0x0002,
138 TP_ACPI_WGSV_STATE_WWANPWRRES = 0x0004,
139 TP_ACPI_WGSV_STATE_WWANBIOSOFF = 0x0008,
140 TP_ACPI_WGSV_STATE_BLTHEXIST = 0x0001,
141 TP_ACPI_WGSV_STATE_BLTHPWR = 0x0002,
142 TP_ACPI_WGSV_STATE_BLTHPWRRES = 0x0004,
143 TP_ACPI_WGSV_STATE_BLTHBIOSOFF = 0x0008,
144 TP_ACPI_WGSV_STATE_UWBEXIST = 0x0010,
145 TP_ACPI_WGSV_STATE_UWBPWR = 0x0020,
146};
147
148
149enum tpacpi_hkey_event_t {
150
151 TP_HKEY_EV_HOTKEY_BASE = 0x1001,
152 TP_HKEY_EV_BRGHT_UP = 0x1010,
153 TP_HKEY_EV_BRGHT_DOWN = 0x1011,
154 TP_HKEY_EV_VOL_UP = 0x1015,
155 TP_HKEY_EV_VOL_DOWN = 0x1016,
156 TP_HKEY_EV_VOL_MUTE = 0x1017,
157
158
159 TP_HKEY_EV_WKUP_S3_UNDOCK = 0x2304,
160 TP_HKEY_EV_WKUP_S4_UNDOCK = 0x2404,
161 TP_HKEY_EV_WKUP_S3_BAYEJ = 0x2305,
162 TP_HKEY_EV_WKUP_S4_BAYEJ = 0x2405,
163 TP_HKEY_EV_WKUP_S3_BATLOW = 0x2313,
164 TP_HKEY_EV_WKUP_S4_BATLOW = 0x2413,
165
166
167 TP_HKEY_EV_BAYEJ_ACK = 0x3003,
168 TP_HKEY_EV_UNDOCK_ACK = 0x4003,
169
170
171 TP_HKEY_EV_OPTDRV_EJ = 0x3006,
172
173
174 TP_HKEY_EV_LID_CLOSE = 0x5001,
175 TP_HKEY_EV_LID_OPEN = 0x5002,
176 TP_HKEY_EV_TABLET_TABLET = 0x5009,
177 TP_HKEY_EV_TABLET_NOTEBOOK = 0x500a,
178 TP_HKEY_EV_PEN_INSERTED = 0x500b,
179 TP_HKEY_EV_PEN_REMOVED = 0x500c,
180 TP_HKEY_EV_BRGHT_CHANGED = 0x5010,
181
182
183 TP_HKEY_EV_ALARM_BAT_HOT = 0x6011,
184 TP_HKEY_EV_ALARM_BAT_XHOT = 0x6012,
185 TP_HKEY_EV_ALARM_SENSOR_HOT = 0x6021,
186 TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022,
187 TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030,
188
189
190 TP_HKEY_EV_RFKILL_CHANGED = 0x7000,
191};
192
193
194
195
196
197#define TPACPI_NAME "thinkpad"
198#define TPACPI_DESC "ThinkPad ACPI Extras"
199#define TPACPI_FILE TPACPI_NAME "_acpi"
200#define TPACPI_URL "http://ibm-acpi.sf.net/"
201#define TPACPI_MAIL "ibm-acpi-devel@lists.sourceforge.net"
202
203#define TPACPI_PROC_DIR "ibm"
204#define TPACPI_ACPI_EVENT_PREFIX "ibm"
205#define TPACPI_DRVR_NAME TPACPI_FILE
206#define TPACPI_DRVR_SHORTNAME "tpacpi"
207#define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon"
208
209#define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd"
210#define TPACPI_WORKQUEUE_NAME "ktpacpid"
211
212#define TPACPI_MAX_ACPI_ARGS 3
213
214
215#define TPACPI_LOG TPACPI_FILE ": "
216#define TPACPI_EMERG KERN_EMERG TPACPI_LOG
217#define TPACPI_ALERT KERN_ALERT TPACPI_LOG
218#define TPACPI_CRIT KERN_CRIT TPACPI_LOG
219#define TPACPI_ERR KERN_ERR TPACPI_LOG
220#define TPACPI_WARN KERN_WARNING TPACPI_LOG
221#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG
222#define TPACPI_INFO KERN_INFO TPACPI_LOG
223#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG
224
225
226#define TPACPI_DBG_ALL 0xffff
227#define TPACPI_DBG_DISCLOSETASK 0x8000
228#define TPACPI_DBG_INIT 0x0001
229#define TPACPI_DBG_EXIT 0x0002
230#define TPACPI_DBG_RFKILL 0x0004
231#define TPACPI_DBG_HKEY 0x0008
232#define TPACPI_DBG_FAN 0x0010
233#define TPACPI_DBG_BRGHT 0x0020
234
235#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
236#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
237#define strlencmp(a, b) (strncmp((a), (b), strlen(b)))
238
239
240
241
242
243
244struct ibm_struct;
245
246struct tp_acpi_drv_struct {
247 const struct acpi_device_id *hid;
248 struct acpi_driver *driver;
249
250 void (*notify) (struct ibm_struct *, u32);
251 acpi_handle *handle;
252 u32 type;
253 struct acpi_device *device;
254};
255
256struct ibm_struct {
257 char *name;
258
259 int (*read) (char *);
260 int (*write) (char *);
261 void (*exit) (void);
262 void (*resume) (void);
263 void (*suspend) (pm_message_t state);
264 void (*shutdown) (void);
265
266 struct list_head all_drivers;
267
268 struct tp_acpi_drv_struct *acpi;
269
270 struct {
271 u8 acpi_driver_registered:1;
272 u8 acpi_notify_installed:1;
273 u8 proc_created:1;
274 u8 init_called:1;
275 u8 experimental:1;
276 } flags;
277};
278
279struct ibm_init_struct {
280 char param[32];
281
282 int (*init) (struct ibm_init_struct *);
283 struct ibm_struct *data;
284};
285
286static struct {
287 u32 bluetooth:1;
288 u32 hotkey:1;
289 u32 hotkey_mask:1;
290 u32 hotkey_wlsw:1;
291 u32 hotkey_tablet:1;
292 u32 light:1;
293 u32 light_status:1;
294 u32 bright_16levels:1;
295 u32 bright_acpimode:1;
296 u32 wan:1;
297 u32 uwb:1;
298 u32 fan_ctrl_status_undef:1;
299 u32 second_fan:1;
300 u32 beep_needs_two_args:1;
301 u32 input_device_registered:1;
302 u32 platform_drv_registered:1;
303 u32 platform_drv_attrs_registered:1;
304 u32 sensors_pdrv_registered:1;
305 u32 sensors_pdrv_attrs_registered:1;
306 u32 sensors_pdev_attrs_registered:1;
307 u32 hotkey_poll_active:1;
308} tp_features;
309
310static struct {
311 u16 hotkey_mask_ff:1;
312} tp_warned;
313
314struct thinkpad_id_data {
315 unsigned int vendor;
316
317
318 char *bios_version_str;
319 char *ec_version_str;
320
321 u16 bios_model;
322 u16 ec_model;
323 u16 bios_release;
324 u16 ec_release;
325
326 char *model_str;
327 char *nummodel_str;
328};
329static struct thinkpad_id_data thinkpad_id;
330
331static enum {
332 TPACPI_LIFE_INIT = 0,
333 TPACPI_LIFE_RUNNING,
334 TPACPI_LIFE_EXITING,
335} tpacpi_lifecycle;
336
337static int experimental;
338static u32 dbg_level;
339
340static struct workqueue_struct *tpacpi_wq;
341
342enum led_status_t {
343 TPACPI_LED_OFF = 0,
344 TPACPI_LED_ON,
345 TPACPI_LED_BLINK,
346};
347
348
349struct tpacpi_led_classdev {
350 struct led_classdev led_classdev;
351 struct work_struct work;
352 enum led_status_t new_state;
353 unsigned int led;
354};
355
356#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
357static int dbg_wlswemul;
358static int tpacpi_wlsw_emulstate;
359static int dbg_bluetoothemul;
360static int tpacpi_bluetooth_emulstate;
361static int dbg_wwanemul;
362static int tpacpi_wwan_emulstate;
363static int dbg_uwbemul;
364static int tpacpi_uwb_emulstate;
365#endif
366
367
368
369
370
371
372#define dbg_printk(a_dbg_level, format, arg...) \
373 do { if (dbg_level & (a_dbg_level)) \
374 printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \
375 } while (0)
376
377#ifdef CONFIG_THINKPAD_ACPI_DEBUG
378#define vdbg_printk dbg_printk
379static const char *str_supported(int is_supported);
380#else
381#define vdbg_printk(a_dbg_level, format, arg...) \
382 do { } while (0)
383#endif
384
385static void tpacpi_log_usertask(const char * const what)
386{
387 printk(TPACPI_DEBUG "%s: access by process with PID %d\n",
388 what, task_tgid_vnr(current));
389}
390
391#define tpacpi_disclose_usertask(what, format, arg...) \
392 do { \
393 if (unlikely( \
394 (dbg_level & TPACPI_DBG_DISCLOSETASK) && \
395 (tpacpi_lifecycle == TPACPI_LIFE_RUNNING))) { \
396 printk(TPACPI_DEBUG "%s: PID %d: " format, \
397 what, task_tgid_vnr(current), ## arg); \
398 } \
399 } while (0)
400
401
402
403
404
405
406
407
408
409
410#define TPACPI_MATCH_ANY 0xffffU
411#define TPACPI_MATCH_UNKNOWN 0U
412
413
414#define TPID(__c1, __c2) (((__c2) << 8) | (__c1))
415
416#define TPACPI_Q_IBM(__id1, __id2, __quirk) \
417 { .vendor = PCI_VENDOR_ID_IBM, \
418 .bios = TPID(__id1, __id2), \
419 .ec = TPACPI_MATCH_ANY, \
420 .quirks = (__quirk) }
421
422#define TPACPI_Q_LNV(__id1, __id2, __quirk) \
423 { .vendor = PCI_VENDOR_ID_LENOVO, \
424 .bios = TPID(__id1, __id2), \
425 .ec = TPACPI_MATCH_ANY, \
426 .quirks = (__quirk) }
427
428struct tpacpi_quirk {
429 unsigned int vendor;
430 u16 bios;
431 u16 ec;
432 unsigned long quirks;
433};
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448static unsigned long __init tpacpi_check_quirks(
449 const struct tpacpi_quirk *qlist,
450 unsigned int qlist_size)
451{
452 while (qlist_size) {
453 if ((qlist->vendor == thinkpad_id.vendor ||
454 qlist->vendor == TPACPI_MATCH_ANY) &&
455 (qlist->bios == thinkpad_id.bios_model ||
456 qlist->bios == TPACPI_MATCH_ANY) &&
457 (qlist->ec == thinkpad_id.ec_model ||
458 qlist->ec == TPACPI_MATCH_ANY))
459 return qlist->quirks;
460
461 qlist_size--;
462 qlist++;
463 }
464 return 0;
465}
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480static acpi_handle root_handle;
481
482#define TPACPI_HANDLE(object, parent, paths...) \
483 static acpi_handle object##_handle; \
484 static acpi_handle *object##_parent = &parent##_handle; \
485 static char *object##_path; \
486 static char *object##_paths[] = { paths }
487
488TPACPI_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",
489 "\\_SB.PCI.ISA.EC",
490 "\\_SB.PCI0.ISA0.EC0",
491 "\\_SB.PCI0.ISA.EC",
492 "\\_SB.PCI0.AD4S.EC0",
493 "\\_SB.PCI0.ICH3.EC0",
494 "\\_SB.PCI0.LPC.EC",
495 );
496
497TPACPI_HANDLE(ecrd, ec, "ECRD");
498TPACPI_HANDLE(ecwr, ec, "ECWR");
499
500TPACPI_HANDLE(cmos, root, "\\UCMS",
501
502 "\\CMOS",
503 "\\CMS",
504 );
505
506TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY",
507 "^HKEY",
508 "HKEY",
509 );
510
511TPACPI_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA",
512 "\\_SB.PCI0.AGP0.VID0",
513 "\\_SB.PCI0.VID0",
514 "\\_SB.PCI0.VID",
515 "\\_SB.PCI0.AGP.VID",
516 );
517
518
519
520
521
522
523static int acpi_evalf(acpi_handle handle,
524 void *res, char *method, char *fmt, ...)
525{
526 char *fmt0 = fmt;
527 struct acpi_object_list params;
528 union acpi_object in_objs[TPACPI_MAX_ACPI_ARGS];
529 struct acpi_buffer result, *resultp;
530 union acpi_object out_obj;
531 acpi_status status;
532 va_list ap;
533 char res_type;
534 int success;
535 int quiet;
536
537 if (!*fmt) {
538 printk(TPACPI_ERR "acpi_evalf() called with empty format\n");
539 return 0;
540 }
541
542 if (*fmt == 'q') {
543 quiet = 1;
544 fmt++;
545 } else
546 quiet = 0;
547
548 res_type = *(fmt++);
549
550 params.count = 0;
551 params.pointer = &in_objs[0];
552
553 va_start(ap, fmt);
554 while (*fmt) {
555 char c = *(fmt++);
556 switch (c) {
557 case 'd':
558 in_objs[params.count].integer.value = va_arg(ap, int);
559 in_objs[params.count++].type = ACPI_TYPE_INTEGER;
560 break;
561
562 default:
563 printk(TPACPI_ERR "acpi_evalf() called "
564 "with invalid format character '%c'\n", c);
565 return 0;
566 }
567 }
568 va_end(ap);
569
570 if (res_type != 'v') {
571 result.length = sizeof(out_obj);
572 result.pointer = &out_obj;
573 resultp = &result;
574 } else
575 resultp = NULL;
576
577 status = acpi_evaluate_object(handle, method, ¶ms, resultp);
578
579 switch (res_type) {
580 case 'd':
581 if (res)
582 *(int *)res = out_obj.integer.value;
583 success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
584 break;
585 case 'v':
586 success = status == AE_OK;
587 break;
588
589 default:
590 printk(TPACPI_ERR "acpi_evalf() called "
591 "with invalid format character '%c'\n", res_type);
592 return 0;
593 }
594
595 if (!success && !quiet)
596 printk(TPACPI_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
597 method, fmt0, status);
598
599 return success;
600}
601
602static int acpi_ec_read(int i, u8 *p)
603{
604 int v;
605
606 if (ecrd_handle) {
607 if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
608 return 0;
609 *p = v;
610 } else {
611 if (ec_read(i, p) < 0)
612 return 0;
613 }
614
615 return 1;
616}
617
618static int acpi_ec_write(int i, u8 v)
619{
620 if (ecwr_handle) {
621 if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
622 return 0;
623 } else {
624 if (ec_write(i, v) < 0)
625 return 0;
626 }
627
628 return 1;
629}
630
631static int issue_thinkpad_cmos_command(int cmos_cmd)
632{
633 if (!cmos_handle)
634 return -ENXIO;
635
636 if (!acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd))
637 return -EIO;
638
639 return 0;
640}
641
642
643
644
645
646#define TPACPI_ACPIHANDLE_INIT(object) \
647 drv_acpi_handle_init(#object, &object##_handle, *object##_parent, \
648 object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
649
650static void drv_acpi_handle_init(char *name,
651 acpi_handle *handle, acpi_handle parent,
652 char **paths, int num_paths, char **path)
653{
654 int i;
655 acpi_status status;
656
657 vdbg_printk(TPACPI_DBG_INIT, "trying to locate ACPI handle for %s\n",
658 name);
659
660 for (i = 0; i < num_paths; i++) {
661 status = acpi_get_handle(parent, paths[i], handle);
662 if (ACPI_SUCCESS(status)) {
663 *path = paths[i];
664 dbg_printk(TPACPI_DBG_INIT,
665 "Found ACPI handle %s for %s\n",
666 *path, name);
667 return;
668 }
669 }
670
671 vdbg_printk(TPACPI_DBG_INIT, "ACPI handle for %s not found\n",
672 name);
673 *handle = NULL;
674}
675
676static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data)
677{
678 struct ibm_struct *ibm = data;
679
680 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
681 return;
682
683 if (!ibm || !ibm->acpi || !ibm->acpi->notify)
684 return;
685
686 ibm->acpi->notify(ibm, event);
687}
688
689static int __init setup_acpi_notify(struct ibm_struct *ibm)
690{
691 acpi_status status;
692 int rc;
693
694 BUG_ON(!ibm->acpi);
695
696 if (!*ibm->acpi->handle)
697 return 0;
698
699 vdbg_printk(TPACPI_DBG_INIT,
700 "setting up ACPI notify for %s\n", ibm->name);
701
702 rc = acpi_bus_get_device(*ibm->acpi->handle, &ibm->acpi->device);
703 if (rc < 0) {
704 printk(TPACPI_ERR "acpi_bus_get_device(%s) failed: %d\n",
705 ibm->name, rc);
706 return -ENODEV;
707 }
708
709 ibm->acpi->device->driver_data = ibm;
710 sprintf(acpi_device_class(ibm->acpi->device), "%s/%s",
711 TPACPI_ACPI_EVENT_PREFIX,
712 ibm->name);
713
714 status = acpi_install_notify_handler(*ibm->acpi->handle,
715 ibm->acpi->type, dispatch_acpi_notify, ibm);
716 if (ACPI_FAILURE(status)) {
717 if (status == AE_ALREADY_EXISTS) {
718 printk(TPACPI_NOTICE
719 "another device driver is already "
720 "handling %s events\n", ibm->name);
721 } else {
722 printk(TPACPI_ERR
723 "acpi_install_notify_handler(%s) failed: %d\n",
724 ibm->name, status);
725 }
726 return -ENODEV;
727 }
728 ibm->flags.acpi_notify_installed = 1;
729 return 0;
730}
731
732static int __init tpacpi_device_add(struct acpi_device *device)
733{
734 return 0;
735}
736
737static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
738{
739 int rc;
740
741 dbg_printk(TPACPI_DBG_INIT,
742 "registering %s as an ACPI driver\n", ibm->name);
743
744 BUG_ON(!ibm->acpi);
745
746 ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
747 if (!ibm->acpi->driver) {
748 printk(TPACPI_ERR
749 "failed to allocate memory for ibm->acpi->driver\n");
750 return -ENOMEM;
751 }
752
753 sprintf(ibm->acpi->driver->name, "%s_%s", TPACPI_NAME, ibm->name);
754 ibm->acpi->driver->ids = ibm->acpi->hid;
755
756 ibm->acpi->driver->ops.add = &tpacpi_device_add;
757
758 rc = acpi_bus_register_driver(ibm->acpi->driver);
759 if (rc < 0) {
760 printk(TPACPI_ERR "acpi_bus_register_driver(%s) failed: %d\n",
761 ibm->name, rc);
762 kfree(ibm->acpi->driver);
763 ibm->acpi->driver = NULL;
764 } else if (!rc)
765 ibm->flags.acpi_driver_registered = 1;
766
767 return rc;
768}
769
770
771
772
773
774
775
776
777
778
779static int dispatch_procfs_read(char *page, char **start, off_t off,
780 int count, int *eof, void *data)
781{
782 struct ibm_struct *ibm = data;
783 int len;
784
785 if (!ibm || !ibm->read)
786 return -EINVAL;
787
788 len = ibm->read(page);
789 if (len < 0)
790 return len;
791
792 if (len <= off + count)
793 *eof = 1;
794 *start = page + off;
795 len -= off;
796 if (len > count)
797 len = count;
798 if (len < 0)
799 len = 0;
800
801 return len;
802}
803
804static int dispatch_procfs_write(struct file *file,
805 const char __user *userbuf,
806 unsigned long count, void *data)
807{
808 struct ibm_struct *ibm = data;
809 char *kernbuf;
810 int ret;
811
812 if (!ibm || !ibm->write)
813 return -EINVAL;
814 if (count > PAGE_SIZE - 2)
815 return -EINVAL;
816
817 kernbuf = kmalloc(count + 2, GFP_KERNEL);
818 if (!kernbuf)
819 return -ENOMEM;
820
821 if (copy_from_user(kernbuf, userbuf, count)) {
822 kfree(kernbuf);
823 return -EFAULT;
824 }
825
826 kernbuf[count] = 0;
827 strcat(kernbuf, ",");
828 ret = ibm->write(kernbuf);
829 if (ret == 0)
830 ret = count;
831
832 kfree(kernbuf);
833
834 return ret;
835}
836
837static char *next_cmd(char **cmds)
838{
839 char *start = *cmds;
840 char *end;
841
842 while ((end = strchr(start, ',')) && end == start)
843 start = end + 1;
844
845 if (!end)
846 return NULL;
847
848 *end = 0;
849 *cmds = end + 1;
850 return start;
851}
852
853
854
855
856
857
858
859
860
861
862static struct platform_device *tpacpi_pdev;
863static struct platform_device *tpacpi_sensors_pdev;
864static struct device *tpacpi_hwmon;
865static struct input_dev *tpacpi_inputdev;
866static struct mutex tpacpi_inputdev_send_mutex;
867static LIST_HEAD(tpacpi_all_drivers);
868
869static int tpacpi_suspend_handler(struct platform_device *pdev,
870 pm_message_t state)
871{
872 struct ibm_struct *ibm, *itmp;
873
874 list_for_each_entry_safe(ibm, itmp,
875 &tpacpi_all_drivers,
876 all_drivers) {
877 if (ibm->suspend)
878 (ibm->suspend)(state);
879 }
880
881 return 0;
882}
883
884static int tpacpi_resume_handler(struct platform_device *pdev)
885{
886 struct ibm_struct *ibm, *itmp;
887
888 list_for_each_entry_safe(ibm, itmp,
889 &tpacpi_all_drivers,
890 all_drivers) {
891 if (ibm->resume)
892 (ibm->resume)();
893 }
894
895 return 0;
896}
897
898static void tpacpi_shutdown_handler(struct platform_device *pdev)
899{
900 struct ibm_struct *ibm, *itmp;
901
902 list_for_each_entry_safe(ibm, itmp,
903 &tpacpi_all_drivers,
904 all_drivers) {
905 if (ibm->shutdown)
906 (ibm->shutdown)();
907 }
908}
909
910static struct platform_driver tpacpi_pdriver = {
911 .driver = {
912 .name = TPACPI_DRVR_NAME,
913 .owner = THIS_MODULE,
914 },
915 .suspend = tpacpi_suspend_handler,
916 .resume = tpacpi_resume_handler,
917 .shutdown = tpacpi_shutdown_handler,
918};
919
920static struct platform_driver tpacpi_hwmon_pdriver = {
921 .driver = {
922 .name = TPACPI_HWMON_DRVR_NAME,
923 .owner = THIS_MODULE,
924 },
925};
926
927
928
929
930
931struct attribute_set {
932 unsigned int members, max_members;
933 struct attribute_group group;
934};
935
936struct attribute_set_obj {
937 struct attribute_set s;
938 struct attribute *a;
939} __attribute__((packed));
940
941static struct attribute_set *create_attr_set(unsigned int max_members,
942 const char *name)
943{
944 struct attribute_set_obj *sobj;
945
946 if (max_members == 0)
947 return NULL;
948
949
950 sobj = kzalloc(sizeof(struct attribute_set_obj) +
951 max_members * sizeof(struct attribute *),
952 GFP_KERNEL);
953 if (!sobj)
954 return NULL;
955 sobj->s.max_members = max_members;
956 sobj->s.group.attrs = &sobj->a;
957 sobj->s.group.name = name;
958
959 return &sobj->s;
960}
961
962#define destroy_attr_set(_set) \
963 kfree(_set);
964
965
966static int add_to_attr_set(struct attribute_set *s, struct attribute *attr)
967{
968 if (!s || !attr)
969 return -EINVAL;
970
971 if (s->members >= s->max_members)
972 return -ENOMEM;
973
974 s->group.attrs[s->members] = attr;
975 s->members++;
976
977 return 0;
978}
979
980static int add_many_to_attr_set(struct attribute_set *s,
981 struct attribute **attr,
982 unsigned int count)
983{
984 int i, res;
985
986 for (i = 0; i < count; i++) {
987 res = add_to_attr_set(s, attr[i]);
988 if (res)
989 return res;
990 }
991
992 return 0;
993}
994
995static void delete_attr_set(struct attribute_set *s, struct kobject *kobj)
996{
997 sysfs_remove_group(kobj, &s->group);
998 destroy_attr_set(s);
999}
1000
1001#define register_attr_set_with_sysfs(_attr_set, _kobj) \
1002 sysfs_create_group(_kobj, &_attr_set->group)
1003
1004static int parse_strtoul(const char *buf,
1005 unsigned long max, unsigned long *value)
1006{
1007 char *endp;
1008
1009 while (*buf && isspace(*buf))
1010 buf++;
1011 *value = simple_strtoul(buf, &endp, 0);
1012 while (*endp && isspace(*endp))
1013 endp++;
1014 if (*endp || *value > max)
1015 return -EINVAL;
1016
1017 return 0;
1018}
1019
1020static void tpacpi_disable_brightness_delay(void)
1021{
1022 if (acpi_evalf(hkey_handle, NULL, "PWMS", "qvd", 0))
1023 printk(TPACPI_NOTICE
1024 "ACPI backlight control delay disabled\n");
1025}
1026
1027static int __init tpacpi_query_bcl_levels(acpi_handle handle)
1028{
1029 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1030 union acpi_object *obj;
1031 int rc;
1032
1033 if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
1034 obj = (union acpi_object *)buffer.pointer;
1035 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
1036 printk(TPACPI_ERR "Unknown _BCL data, "
1037 "please report this to %s\n", TPACPI_MAIL);
1038 rc = 0;
1039 } else {
1040 rc = obj->package.count;
1041 }
1042 } else {
1043 return 0;
1044 }
1045
1046 kfree(buffer.pointer);
1047 return rc;
1048}
1049
1050static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
1051 u32 lvl, void *context, void **rv)
1052{
1053 char name[ACPI_PATH_SEGMENT_LENGTH];
1054 struct acpi_buffer buffer = { sizeof(name), &name };
1055
1056 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
1057 !strncmp("_BCL", name, sizeof(name) - 1)) {
1058 BUG_ON(!rv || !*rv);
1059 **(int **)rv = tpacpi_query_bcl_levels(handle);
1060 return AE_CTRL_TERMINATE;
1061 } else {
1062 return AE_OK;
1063 }
1064}
1065
1066
1067
1068
1069static int __init tpacpi_check_std_acpi_brightness_support(void)
1070{
1071 int status;
1072 int bcl_levels = 0;
1073 void *bcl_ptr = &bcl_levels;
1074
1075 if (!vid_handle) {
1076 TPACPI_ACPIHANDLE_INIT(vid);
1077 }
1078 if (!vid_handle)
1079 return 0;
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
1090 tpacpi_acpi_walk_find_bcl, NULL,
1091 &bcl_ptr);
1092
1093 if (ACPI_SUCCESS(status) && bcl_levels > 2) {
1094 tp_features.bright_acpimode = 1;
1095 return (bcl_levels - 2);
1096 }
1097
1098 return 0;
1099}
1100
1101static void printk_deprecated_attribute(const char * const what,
1102 const char * const details)
1103{
1104 tpacpi_log_usertask("deprecated sysfs attribute");
1105 printk(TPACPI_WARN "WARNING: sysfs attribute %s is deprecated and "
1106 "will be removed. %s\n",
1107 what, details);
1108}
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134enum tpacpi_rfkill_state {
1135 TPACPI_RFK_RADIO_OFF = 0,
1136 TPACPI_RFK_RADIO_ON
1137};
1138
1139
1140enum tpacpi_rfk_id {
1141 TPACPI_RFK_BLUETOOTH_SW_ID = 0,
1142 TPACPI_RFK_WWAN_SW_ID,
1143 TPACPI_RFK_UWB_SW_ID,
1144 TPACPI_RFK_SW_MAX
1145};
1146
1147static const char *tpacpi_rfkill_names[] = {
1148 [TPACPI_RFK_BLUETOOTH_SW_ID] = "bluetooth",
1149 [TPACPI_RFK_WWAN_SW_ID] = "wwan",
1150 [TPACPI_RFK_UWB_SW_ID] = "uwb",
1151 [TPACPI_RFK_SW_MAX] = NULL
1152};
1153
1154
1155struct tpacpi_rfk {
1156 struct rfkill *rfkill;
1157 enum tpacpi_rfk_id id;
1158 const struct tpacpi_rfk_ops *ops;
1159};
1160
1161struct tpacpi_rfk_ops {
1162
1163 int (*get_status)(void);
1164 int (*set_status)(const enum tpacpi_rfkill_state);
1165};
1166
1167static struct tpacpi_rfk *tpacpi_rfkill_switches[TPACPI_RFK_SW_MAX];
1168
1169
1170static int tpacpi_rfk_update_swstate(const struct tpacpi_rfk *tp_rfk)
1171{
1172 int status;
1173
1174 if (!tp_rfk)
1175 return -ENODEV;
1176
1177 status = (tp_rfk->ops->get_status)();
1178 if (status < 0)
1179 return status;
1180
1181 rfkill_set_sw_state(tp_rfk->rfkill,
1182 (status == TPACPI_RFK_RADIO_OFF));
1183
1184 return status;
1185}
1186
1187
1188static void tpacpi_rfk_update_swstate_all(void)
1189{
1190 unsigned int i;
1191
1192 for (i = 0; i < TPACPI_RFK_SW_MAX; i++)
1193 tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[i]);
1194}
1195
1196
1197
1198
1199
1200static void tpacpi_rfk_update_hwblock_state(bool blocked)
1201{
1202 unsigned int i;
1203 struct tpacpi_rfk *tp_rfk;
1204
1205 for (i = 0; i < TPACPI_RFK_SW_MAX; i++) {
1206 tp_rfk = tpacpi_rfkill_switches[i];
1207 if (tp_rfk) {
1208 if (rfkill_set_hw_state(tp_rfk->rfkill,
1209 blocked)) {
1210
1211 }
1212 }
1213 }
1214}
1215
1216
1217static int hotkey_get_wlsw(void);
1218
1219
1220static bool tpacpi_rfk_check_hwblock_state(void)
1221{
1222 int res = hotkey_get_wlsw();
1223 int hw_blocked;
1224
1225
1226 if (res < 0)
1227 return false;
1228
1229 hw_blocked = (res == TPACPI_RFK_RADIO_OFF);
1230 tpacpi_rfk_update_hwblock_state(hw_blocked);
1231
1232 return hw_blocked;
1233}
1234
1235static int tpacpi_rfk_hook_set_block(void *data, bool blocked)
1236{
1237 struct tpacpi_rfk *tp_rfk = data;
1238 int res;
1239
1240 dbg_printk(TPACPI_DBG_RFKILL,
1241 "request to change radio state to %s\n",
1242 blocked ? "blocked" : "unblocked");
1243
1244
1245 res = (tp_rfk->ops->set_status)(blocked ?
1246 TPACPI_RFK_RADIO_OFF : TPACPI_RFK_RADIO_ON);
1247
1248
1249 tpacpi_rfk_update_swstate(tp_rfk);
1250
1251 return (res < 0) ? res : 0;
1252}
1253
1254static const struct rfkill_ops tpacpi_rfk_rfkill_ops = {
1255 .set_block = tpacpi_rfk_hook_set_block,
1256};
1257
1258static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1259 const struct tpacpi_rfk_ops *tp_rfkops,
1260 const enum rfkill_type rfktype,
1261 const char *name,
1262 const bool set_default)
1263{
1264 struct tpacpi_rfk *atp_rfk;
1265 int res;
1266 bool sw_state = false;
1267 int sw_status;
1268
1269 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
1270
1271 atp_rfk = kzalloc(sizeof(struct tpacpi_rfk), GFP_KERNEL);
1272 if (atp_rfk)
1273 atp_rfk->rfkill = rfkill_alloc(name,
1274 &tpacpi_pdev->dev,
1275 rfktype,
1276 &tpacpi_rfk_rfkill_ops,
1277 atp_rfk);
1278 if (!atp_rfk || !atp_rfk->rfkill) {
1279 printk(TPACPI_ERR
1280 "failed to allocate memory for rfkill class\n");
1281 kfree(atp_rfk);
1282 return -ENOMEM;
1283 }
1284
1285 atp_rfk->id = id;
1286 atp_rfk->ops = tp_rfkops;
1287
1288 sw_status = (tp_rfkops->get_status)();
1289 if (sw_status < 0) {
1290 printk(TPACPI_ERR
1291 "failed to read initial state for %s, error %d\n",
1292 name, sw_status);
1293 } else {
1294 sw_state = (sw_status == TPACPI_RFK_RADIO_OFF);
1295 if (set_default) {
1296
1297
1298 rfkill_init_sw_state(atp_rfk->rfkill, sw_state);
1299 }
1300 }
1301 rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state());
1302
1303 res = rfkill_register(atp_rfk->rfkill);
1304 if (res < 0) {
1305 printk(TPACPI_ERR
1306 "failed to register %s rfkill switch: %d\n",
1307 name, res);
1308 rfkill_destroy(atp_rfk->rfkill);
1309 kfree(atp_rfk);
1310 return res;
1311 }
1312
1313 tpacpi_rfkill_switches[id] = atp_rfk;
1314 return 0;
1315}
1316
1317static void tpacpi_destroy_rfkill(const enum tpacpi_rfk_id id)
1318{
1319 struct tpacpi_rfk *tp_rfk;
1320
1321 BUG_ON(id >= TPACPI_RFK_SW_MAX);
1322
1323 tp_rfk = tpacpi_rfkill_switches[id];
1324 if (tp_rfk) {
1325 rfkill_unregister(tp_rfk->rfkill);
1326 rfkill_destroy(tp_rfk->rfkill);
1327 tpacpi_rfkill_switches[id] = NULL;
1328 kfree(tp_rfk);
1329 }
1330}
1331
1332static void printk_deprecated_rfkill_attribute(const char * const what)
1333{
1334 printk_deprecated_attribute(what,
1335 "Please switch to generic rfkill before year 2010");
1336}
1337
1338
1339static ssize_t tpacpi_rfk_sysfs_enable_show(const enum tpacpi_rfk_id id,
1340 struct device_attribute *attr,
1341 char *buf)
1342{
1343 int status;
1344
1345 printk_deprecated_rfkill_attribute(attr->attr.name);
1346
1347
1348 if (tpacpi_rfk_check_hwblock_state()) {
1349 status = TPACPI_RFK_RADIO_OFF;
1350 } else {
1351 status = tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]);
1352 if (status < 0)
1353 return status;
1354 }
1355
1356 return snprintf(buf, PAGE_SIZE, "%d\n",
1357 (status == TPACPI_RFK_RADIO_ON) ? 1 : 0);
1358}
1359
1360static ssize_t tpacpi_rfk_sysfs_enable_store(const enum tpacpi_rfk_id id,
1361 struct device_attribute *attr,
1362 const char *buf, size_t count)
1363{
1364 unsigned long t;
1365 int res;
1366
1367 printk_deprecated_rfkill_attribute(attr->attr.name);
1368
1369 if (parse_strtoul(buf, 1, &t))
1370 return -EINVAL;
1371
1372 tpacpi_disclose_usertask(attr->attr.name, "set to %ld\n", t);
1373
1374
1375 if (tpacpi_rfk_check_hwblock_state() && !!t)
1376 return -EPERM;
1377
1378 res = tpacpi_rfkill_switches[id]->ops->set_status((!!t) ?
1379 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF);
1380 tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]);
1381
1382 return (res < 0) ? res : count;
1383}
1384
1385
1386static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p)
1387{
1388 int len = 0;
1389
1390 if (id >= TPACPI_RFK_SW_MAX)
1391 len += sprintf(p + len, "status:\t\tnot supported\n");
1392 else {
1393 int status;
1394
1395
1396 if (tpacpi_rfk_check_hwblock_state()) {
1397 status = TPACPI_RFK_RADIO_OFF;
1398 } else {
1399 status = tpacpi_rfk_update_swstate(
1400 tpacpi_rfkill_switches[id]);
1401 if (status < 0)
1402 return status;
1403 }
1404
1405 len += sprintf(p + len, "status:\t\t%s\n",
1406 (status == TPACPI_RFK_RADIO_ON) ?
1407 "enabled" : "disabled");
1408 len += sprintf(p + len, "commands:\tenable, disable\n");
1409 }
1410
1411 return len;
1412}
1413
1414static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf)
1415{
1416 char *cmd;
1417 int status = -1;
1418 int res = 0;
1419
1420 if (id >= TPACPI_RFK_SW_MAX)
1421 return -ENODEV;
1422
1423 while ((cmd = next_cmd(&buf))) {
1424 if (strlencmp(cmd, "enable") == 0)
1425 status = TPACPI_RFK_RADIO_ON;
1426 else if (strlencmp(cmd, "disable") == 0)
1427 status = TPACPI_RFK_RADIO_OFF;
1428 else
1429 return -EINVAL;
1430 }
1431
1432 if (status != -1) {
1433 tpacpi_disclose_usertask("procfs", "attempt to %s %s\n",
1434 (status == TPACPI_RFK_RADIO_ON) ?
1435 "enable" : "disable",
1436 tpacpi_rfkill_names[id]);
1437 res = (tpacpi_rfkill_switches[id]->ops->set_status)(status);
1438 tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]);
1439 }
1440
1441 return res;
1442}
1443
1444
1445
1446
1447
1448
1449static ssize_t tpacpi_driver_interface_version_show(
1450 struct device_driver *drv,
1451 char *buf)
1452{
1453 return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION);
1454}
1455
1456static DRIVER_ATTR(interface_version, S_IRUGO,
1457 tpacpi_driver_interface_version_show, NULL);
1458
1459
1460static ssize_t tpacpi_driver_debug_show(struct device_driver *drv,
1461 char *buf)
1462{
1463 return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level);
1464}
1465
1466static ssize_t tpacpi_driver_debug_store(struct device_driver *drv,
1467 const char *buf, size_t count)
1468{
1469 unsigned long t;
1470
1471 if (parse_strtoul(buf, 0xffff, &t))
1472 return -EINVAL;
1473
1474 dbg_level = t;
1475
1476 return count;
1477}
1478
1479static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
1480 tpacpi_driver_debug_show, tpacpi_driver_debug_store);
1481
1482
1483static ssize_t tpacpi_driver_version_show(struct device_driver *drv,
1484 char *buf)
1485{
1486 return snprintf(buf, PAGE_SIZE, "%s v%s\n",
1487 TPACPI_DESC, TPACPI_VERSION);
1488}
1489
1490static DRIVER_ATTR(version, S_IRUGO,
1491 tpacpi_driver_version_show, NULL);
1492
1493
1494
1495#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
1496
1497
1498static ssize_t tpacpi_driver_wlsw_emulstate_show(struct device_driver *drv,
1499 char *buf)
1500{
1501 return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wlsw_emulstate);
1502}
1503
1504static ssize_t tpacpi_driver_wlsw_emulstate_store(struct device_driver *drv,
1505 const char *buf, size_t count)
1506{
1507 unsigned long t;
1508
1509 if (parse_strtoul(buf, 1, &t))
1510 return -EINVAL;
1511
1512 if (tpacpi_wlsw_emulstate != !!t) {
1513 tpacpi_wlsw_emulstate = !!t;
1514 tpacpi_rfk_update_hwblock_state(!t);
1515 }
1516
1517 return count;
1518}
1519
1520static DRIVER_ATTR(wlsw_emulstate, S_IWUSR | S_IRUGO,
1521 tpacpi_driver_wlsw_emulstate_show,
1522 tpacpi_driver_wlsw_emulstate_store);
1523
1524
1525static ssize_t tpacpi_driver_bluetooth_emulstate_show(
1526 struct device_driver *drv,
1527 char *buf)
1528{
1529 return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_bluetooth_emulstate);
1530}
1531
1532static ssize_t tpacpi_driver_bluetooth_emulstate_store(
1533 struct device_driver *drv,
1534 const char *buf, size_t count)
1535{
1536 unsigned long t;
1537
1538 if (parse_strtoul(buf, 1, &t))
1539 return -EINVAL;
1540
1541 tpacpi_bluetooth_emulstate = !!t;
1542
1543 return count;
1544}
1545
1546static DRIVER_ATTR(bluetooth_emulstate, S_IWUSR | S_IRUGO,
1547 tpacpi_driver_bluetooth_emulstate_show,
1548 tpacpi_driver_bluetooth_emulstate_store);
1549
1550
1551static ssize_t tpacpi_driver_wwan_emulstate_show(
1552 struct device_driver *drv,
1553 char *buf)
1554{
1555 return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wwan_emulstate);
1556}
1557
1558static ssize_t tpacpi_driver_wwan_emulstate_store(
1559 struct device_driver *drv,
1560 const char *buf, size_t count)
1561{
1562 unsigned long t;
1563
1564 if (parse_strtoul(buf, 1, &t))
1565 return -EINVAL;
1566
1567 tpacpi_wwan_emulstate = !!t;
1568
1569 return count;
1570}
1571
1572static DRIVER_ATTR(wwan_emulstate, S_IWUSR | S_IRUGO,
1573 tpacpi_driver_wwan_emulstate_show,
1574 tpacpi_driver_wwan_emulstate_store);
1575
1576
1577static ssize_t tpacpi_driver_uwb_emulstate_show(
1578 struct device_driver *drv,
1579 char *buf)
1580{
1581 return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_uwb_emulstate);
1582}
1583
1584static ssize_t tpacpi_driver_uwb_emulstate_store(
1585 struct device_driver *drv,
1586 const char *buf, size_t count)
1587{
1588 unsigned long t;
1589
1590 if (parse_strtoul(buf, 1, &t))
1591 return -EINVAL;
1592
1593 tpacpi_uwb_emulstate = !!t;
1594
1595 return count;
1596}
1597
1598static DRIVER_ATTR(uwb_emulstate, S_IWUSR | S_IRUGO,
1599 tpacpi_driver_uwb_emulstate_show,
1600 tpacpi_driver_uwb_emulstate_store);
1601#endif
1602
1603
1604
1605static struct driver_attribute *tpacpi_driver_attributes[] = {
1606 &driver_attr_debug_level, &driver_attr_version,
1607 &driver_attr_interface_version,
1608};
1609
1610static int __init tpacpi_create_driver_attributes(struct device_driver *drv)
1611{
1612 int i, res;
1613
1614 i = 0;
1615 res = 0;
1616 while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) {
1617 res = driver_create_file(drv, tpacpi_driver_attributes[i]);
1618 i++;
1619 }
1620
1621#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
1622 if (!res && dbg_wlswemul)
1623 res = driver_create_file(drv, &driver_attr_wlsw_emulstate);
1624 if (!res && dbg_bluetoothemul)
1625 res = driver_create_file(drv, &driver_attr_bluetooth_emulstate);
1626 if (!res && dbg_wwanemul)
1627 res = driver_create_file(drv, &driver_attr_wwan_emulstate);
1628 if (!res && dbg_uwbemul)
1629 res = driver_create_file(drv, &driver_attr_uwb_emulstate);
1630#endif
1631
1632 return res;
1633}
1634
1635static void tpacpi_remove_driver_attributes(struct device_driver *drv)
1636{
1637 int i;
1638
1639 for (i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
1640 driver_remove_file(drv, tpacpi_driver_attributes[i]);
1641
1642#ifdef THINKPAD_ACPI_DEBUGFACILITIES
1643 driver_remove_file(drv, &driver_attr_wlsw_emulstate);
1644 driver_remove_file(drv, &driver_attr_bluetooth_emulstate);
1645 driver_remove_file(drv, &driver_attr_wwan_emulstate);
1646 driver_remove_file(drv, &driver_attr_uwb_emulstate);
1647#endif
1648}
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675#define TPV_Q(__v, __id1, __id2, __bv1, __bv2) \
1676 { .vendor = (__v), \
1677 .bios = TPID(__id1, __id2), \
1678 .ec = TPACPI_MATCH_ANY, \
1679 .quirks = TPACPI_MATCH_ANY << 16 \
1680 | (__bv1) << 8 | (__bv2) }
1681
1682#define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \
1683 __eid, __ev1, __ev2) \
1684 { .vendor = (__v), \
1685 .bios = TPID(__bid1, __bid2), \
1686 .ec = __eid, \
1687 .quirks = (__ev1) << 24 | (__ev2) << 16 \
1688 | (__bv1) << 8 | (__bv2) }
1689
1690#define TPV_QI0(__id1, __id2, __bv1, __bv2) \
1691 TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2)
1692
1693
1694#define TPV_QI1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \
1695 TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \
1696 __bv1, __bv2, TPID(__id1, __id2), \
1697 __ev1, __ev2), \
1698 TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \
1699 __bv1, __bv2, TPACPI_MATCH_UNKNOWN, \
1700 __ev1, __ev2)
1701
1702
1703#define TPV_QI2(__bid1, __bid2, __bv1, __bv2, \
1704 __eid1, __eid2, __ev1, __ev2) \
1705 TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \
1706 __bv1, __bv2, TPID(__eid1, __eid2), \
1707 __ev1, __ev2), \
1708 TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \
1709 __bv1, __bv2, TPACPI_MATCH_UNKNOWN, \
1710 __ev1, __ev2)
1711
1712#define TPV_QL0(__id1, __id2, __bv1, __bv2) \
1713 TPV_Q(PCI_VENDOR_ID_LENOVO, __id1, __id2, __bv1, __bv2)
1714
1715#define TPV_QL1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \
1716 TPV_Q_X(PCI_VENDOR_ID_LENOVO, __id1, __id2, \
1717 __bv1, __bv2, TPID(__id1, __id2), \
1718 __ev1, __ev2)
1719
1720#define TPV_QL2(__bid1, __bid2, __bv1, __bv2, \
1721 __eid1, __eid2, __ev1, __ev2) \
1722 TPV_Q_X(PCI_VENDOR_ID_LENOVO, __bid1, __bid2, \
1723 __bv1, __bv2, TPID(__eid1, __eid2), \
1724 __ev1, __ev2)
1725
1726static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1727
1728
1729 TPV_QI0('I', 'M', '6', '5'),
1730 TPV_QI0('I', 'U', '2', '6'),
1731 TPV_QI0('I', 'B', '5', '4'),
1732 TPV_QI0('I', 'H', '4', '7'),
1733 TPV_QI0('I', 'N', '3', '6'),
1734 TPV_QI0('I', 'T', '5', '5'),
1735 TPV_QI0('I', 'D', '4', '8'),
1736 TPV_QI0('I', 'I', '4', '2'),
1737 TPV_QI0('I', 'O', '2', '3'),
1738
1739
1740
1741 TPV_QI0('I', 'W', '5', '9'),
1742 TPV_QI0('I', 'V', '6', '9'),
1743 TPV_QI0('1', '0', '2', '6'),
1744 TPV_QI0('K', 'U', '3', '6'),
1745 TPV_QI0('K', 'X', '3', '6'),
1746 TPV_QI0('K', 'Y', '3', '8'),
1747 TPV_QI0('1', 'B', '1', '7'),
1748 TPV_QI0('1', '3', '2', '0'),
1749 TPV_QI0('1', 'E', '7', '3'),
1750 TPV_QI1('1', 'G', '4', '1', '1', '7'),
1751 TPV_QI1('1', 'N', '1', '6', '0', '7'),
1752
1753
1754
1755 TPV_QI0('1', 'T', 'A', '6'),
1756 TPV_QI0('1', 'X', '5', '7'),
1757
1758
1759
1760 TPV_QI0('1', 'C', 'F', '0'),
1761 TPV_QI0('1', 'F', 'F', '1'),
1762 TPV_QI0('1', 'M', '9', '7'),
1763 TPV_QI0('1', 'O', '6', '1'),
1764 TPV_QI0('1', 'P', '6', '5'),
1765 TPV_QI0('1', 'S', '7', '0'),
1766 TPV_QI1('1', 'R', 'D', 'R', '7', '1'),
1767
1768 TPV_QI1('1', 'V', '7', '1', '2', '8'),
1769 TPV_QI1('7', '8', '7', '1', '0', '6'),
1770 TPV_QI1('7', '6', '6', '9', '1', '6'),
1771 TPV_QI1('7', '0', '6', '9', '2', '8'),
1772
1773 TPV_QI0('I', 'Y', '6', '1'),
1774 TPV_QI0('K', 'Z', '3', '4'),
1775 TPV_QI0('1', '6', '3', '2'),
1776 TPV_QI1('1', 'A', '6', '4', '2', '3'),
1777 TPV_QI1('1', 'I', '7', '1', '2', '0'),
1778 TPV_QI1('1', 'Y', '6', '5', '2', '9'),
1779
1780 TPV_QL1('7', '9', 'E', '3', '5', '0'),
1781 TPV_QL1('7', 'C', 'D', '2', '2', '2'),
1782 TPV_QL0('7', 'E', 'D', '0'),
1783
1784
1785 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'),
1786 TPV_QL2('7', 'I', '3', '4', '7', '9', '5', '0'),
1787
1788
1789
1790 TPV_QI0('I', 'Z', '9', 'D'),
1791 TPV_QI0('1', 'D', '7', '0'),
1792 TPV_QI1('1', 'K', '4', '8', '1', '8'),
1793 TPV_QI1('1', 'Q', '9', '7', '2', '3'),
1794 TPV_QI1('1', 'U', 'D', '3', 'B', '2'),
1795 TPV_QI1('7', '4', '6', '4', '2', '7'),
1796 TPV_QI1('7', '5', '6', '0', '2', '0'),
1797
1798 TPV_QL0('7', 'B', 'D', '7'),
1799 TPV_QL0('7', 'J', '3', '0'),
1800
1801
1802
1803};
1804
1805#undef TPV_QL1
1806#undef TPV_QL0
1807#undef TPV_QI2
1808#undef TPV_QI1
1809#undef TPV_QI0
1810#undef TPV_Q_X
1811#undef TPV_Q
1812
1813static void __init tpacpi_check_outdated_fw(void)
1814{
1815 unsigned long fwvers;
1816 u16 ec_version, bios_version;
1817
1818 fwvers = tpacpi_check_quirks(tpacpi_bios_version_qtable,
1819 ARRAY_SIZE(tpacpi_bios_version_qtable));
1820
1821 if (!fwvers)
1822 return;
1823
1824 bios_version = fwvers & 0xffffU;
1825 ec_version = (fwvers >> 16) & 0xffffU;
1826
1827
1828 if ((bios_version > thinkpad_id.bios_release) ||
1829 (ec_version > thinkpad_id.ec_release &&
1830 ec_version != TPACPI_MATCH_ANY)) {
1831
1832
1833
1834
1835
1836
1837
1838 printk(TPACPI_WARN
1839 "WARNING: Outdated ThinkPad BIOS/EC firmware\n");
1840 printk(TPACPI_WARN
1841 "WARNING: This firmware may be missing critical bug "
1842 "fixes and/or important features\n");
1843 }
1844}
1845
1846static bool __init tpacpi_is_fw_known(void)
1847{
1848 return tpacpi_check_quirks(tpacpi_bios_version_qtable,
1849 ARRAY_SIZE(tpacpi_bios_version_qtable)) != 0;
1850}
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
1865{
1866 printk(TPACPI_INFO "%s v%s\n", TPACPI_DESC, TPACPI_VERSION);
1867 printk(TPACPI_INFO "%s\n", TPACPI_URL);
1868
1869 printk(TPACPI_INFO "ThinkPad BIOS %s, EC %s\n",
1870 (thinkpad_id.bios_version_str) ?
1871 thinkpad_id.bios_version_str : "unknown",
1872 (thinkpad_id.ec_version_str) ?
1873 thinkpad_id.ec_version_str : "unknown");
1874
1875 if (thinkpad_id.vendor && thinkpad_id.model_str)
1876 printk(TPACPI_INFO "%s %s, model %s\n",
1877 (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
1878 "IBM" : ((thinkpad_id.vendor ==
1879 PCI_VENDOR_ID_LENOVO) ?
1880 "Lenovo" : "Unknown vendor"),
1881 thinkpad_id.model_str,
1882 (thinkpad_id.nummodel_str) ?
1883 thinkpad_id.nummodel_str : "unknown");
1884
1885 tpacpi_check_outdated_fw();
1886 return 0;
1887}
1888
1889static int thinkpad_acpi_driver_read(char *p)
1890{
1891 int len = 0;
1892
1893 len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC);
1894 len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION);
1895
1896 return len;
1897}
1898
1899static struct ibm_struct thinkpad_acpi_driver_data = {
1900 .name = "driver",
1901 .read = thinkpad_acpi_driver_read,
1902};
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929enum {
1930 TP_ACPI_HOTKEYSCAN_FNF1 = 0,
1931 TP_ACPI_HOTKEYSCAN_FNF2,
1932 TP_ACPI_HOTKEYSCAN_FNF3,
1933 TP_ACPI_HOTKEYSCAN_FNF4,
1934 TP_ACPI_HOTKEYSCAN_FNF5,
1935 TP_ACPI_HOTKEYSCAN_FNF6,
1936 TP_ACPI_HOTKEYSCAN_FNF7,
1937 TP_ACPI_HOTKEYSCAN_FNF8,
1938 TP_ACPI_HOTKEYSCAN_FNF9,
1939 TP_ACPI_HOTKEYSCAN_FNF10,
1940 TP_ACPI_HOTKEYSCAN_FNF11,
1941 TP_ACPI_HOTKEYSCAN_FNF12,
1942 TP_ACPI_HOTKEYSCAN_FNBACKSPACE,
1943 TP_ACPI_HOTKEYSCAN_FNINSERT,
1944 TP_ACPI_HOTKEYSCAN_FNDELETE,
1945 TP_ACPI_HOTKEYSCAN_FNHOME,
1946 TP_ACPI_HOTKEYSCAN_FNEND,
1947 TP_ACPI_HOTKEYSCAN_FNPAGEUP,
1948 TP_ACPI_HOTKEYSCAN_FNPAGEDOWN,
1949 TP_ACPI_HOTKEYSCAN_FNSPACE,
1950 TP_ACPI_HOTKEYSCAN_VOLUMEUP,
1951 TP_ACPI_HOTKEYSCAN_VOLUMEDOWN,
1952 TP_ACPI_HOTKEYSCAN_MUTE,
1953 TP_ACPI_HOTKEYSCAN_THINKPAD,
1954};
1955
1956enum {
1957 TPACPI_HKEY_NVRAM_KNOWN_MASK = 0x00fb88c0U,
1958 TPACPI_HKEY_NVRAM_GOOD_MASK = 0x00fb8000U,
1959};
1960
1961enum {
1962 TP_ACPI_HKEY_DISPSWTCH_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNF7,
1963 TP_ACPI_HKEY_DISPXPAND_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNF8,
1964 TP_ACPI_HKEY_HIBERNATE_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNF12,
1965 TP_ACPI_HKEY_BRGHTUP_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNHOME,
1966 TP_ACPI_HKEY_BRGHTDWN_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNEND,
1967 TP_ACPI_HKEY_THNKLGHT_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNPAGEUP,
1968 TP_ACPI_HKEY_ZOOM_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNSPACE,
1969 TP_ACPI_HKEY_VOLUP_MASK = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEUP,
1970 TP_ACPI_HKEY_VOLDWN_MASK = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEDOWN,
1971 TP_ACPI_HKEY_MUTE_MASK = 1 << TP_ACPI_HOTKEYSCAN_MUTE,
1972 TP_ACPI_HKEY_THINKPAD_MASK = 1 << TP_ACPI_HOTKEYSCAN_THINKPAD,
1973};
1974
1975enum {
1976 TP_NVRAM_HKEY_GROUP_HK2 = TP_ACPI_HKEY_THINKPAD_MASK |
1977 TP_ACPI_HKEY_ZOOM_MASK |
1978 TP_ACPI_HKEY_DISPSWTCH_MASK |
1979 TP_ACPI_HKEY_HIBERNATE_MASK,
1980 TP_NVRAM_HKEY_GROUP_BRIGHTNESS = TP_ACPI_HKEY_BRGHTUP_MASK |
1981 TP_ACPI_HKEY_BRGHTDWN_MASK,
1982 TP_NVRAM_HKEY_GROUP_VOLUME = TP_ACPI_HKEY_VOLUP_MASK |
1983 TP_ACPI_HKEY_VOLDWN_MASK |
1984 TP_ACPI_HKEY_MUTE_MASK,
1985};
1986
1987#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
1988struct tp_nvram_state {
1989 u16 thinkpad_toggle:1;
1990 u16 zoom_toggle:1;
1991 u16 display_toggle:1;
1992 u16 thinklight_toggle:1;
1993 u16 hibernate_toggle:1;
1994 u16 displayexp_toggle:1;
1995 u16 display_state:1;
1996 u16 brightness_toggle:1;
1997 u16 volume_toggle:1;
1998 u16 mute:1;
1999
2000 u8 brightness_level;
2001 u8 volume_level;
2002};
2003
2004
2005static struct task_struct *tpacpi_hotkey_task;
2006
2007
2008static struct mutex hotkey_thread_mutex;
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019static struct mutex hotkey_thread_data_mutex;
2020static unsigned int hotkey_config_change;
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032static u32 hotkey_source_mask;
2033static unsigned int hotkey_poll_freq = 10;
2034
2035#define HOTKEY_CONFIG_CRITICAL_START \
2036 do { \
2037 mutex_lock(&hotkey_thread_data_mutex); \
2038 hotkey_config_change++; \
2039 } while (0);
2040#define HOTKEY_CONFIG_CRITICAL_END \
2041 mutex_unlock(&hotkey_thread_data_mutex);
2042
2043#else
2044
2045#define hotkey_source_mask 0U
2046#define HOTKEY_CONFIG_CRITICAL_START
2047#define HOTKEY_CONFIG_CRITICAL_END
2048
2049#endif
2050
2051static struct mutex hotkey_mutex;
2052
2053static enum {
2054 TP_ACPI_WAKEUP_NONE = 0,
2055 TP_ACPI_WAKEUP_BAYEJ,
2056 TP_ACPI_WAKEUP_UNDOCK,
2057} hotkey_wakeup_reason;
2058
2059static int hotkey_autosleep_ack;
2060
2061static u32 hotkey_orig_mask;
2062static u32 hotkey_all_mask;
2063static u32 hotkey_reserved_mask;
2064static u32 hotkey_driver_mask;
2065static u32 hotkey_user_mask;
2066static u32 hotkey_acpi_mask;
2067
2068static unsigned int hotkey_report_mode;
2069
2070static u16 *hotkey_keycode_map;
2071
2072static struct attribute_set *hotkey_dev_attributes;
2073
2074static void tpacpi_driver_event(const unsigned int hkey_event);
2075static void hotkey_driver_event(const unsigned int scancode);
2076
2077
2078#define TP_HOTKEY_TABLET_MASK (1 << 3)
2079
2080static int hotkey_get_wlsw(void)
2081{
2082 int status;
2083
2084 if (!tp_features.hotkey_wlsw)
2085 return -ENODEV;
2086
2087#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
2088 if (dbg_wlswemul)
2089 return (tpacpi_wlsw_emulstate) ?
2090 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
2091#endif
2092
2093 if (!acpi_evalf(hkey_handle, &status, "WLSW", "d"))
2094 return -EIO;
2095
2096 return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
2097}
2098
2099static int hotkey_get_tablet_mode(int *status)
2100{
2101 int s;
2102
2103 if (!acpi_evalf(hkey_handle, &s, "MHKG", "d"))
2104 return -EIO;
2105
2106 *status = ((s & TP_HOTKEY_TABLET_MASK) != 0);
2107 return 0;
2108}
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118static int hotkey_mask_get(void)
2119{
2120 if (tp_features.hotkey_mask) {
2121 u32 m = 0;
2122
2123 if (!acpi_evalf(hkey_handle, &m, "DHKN", "d"))
2124 return -EIO;
2125
2126 hotkey_acpi_mask = m;
2127 } else {
2128
2129 hotkey_acpi_mask = hotkey_all_mask;
2130 }
2131
2132
2133 hotkey_user_mask &= (hotkey_acpi_mask | hotkey_source_mask);
2134
2135 return 0;
2136}
2137
2138void static hotkey_mask_warn_incomplete_mask(void)
2139{
2140
2141 const u32 wantedmask = hotkey_driver_mask &
2142 ~(hotkey_acpi_mask | hotkey_source_mask) &
2143 (hotkey_all_mask | TPACPI_HKEY_NVRAM_KNOWN_MASK);
2144
2145 if (wantedmask)
2146 printk(TPACPI_NOTICE
2147 "required events 0x%08x not enabled!\n",
2148 wantedmask);
2149}
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160static int hotkey_mask_set(u32 mask)
2161{
2162 int i;
2163 int rc = 0;
2164
2165 const u32 fwmask = mask & ~hotkey_source_mask;
2166
2167 if (tp_features.hotkey_mask) {
2168 for (i = 0; i < 32; i++) {
2169 if (!acpi_evalf(hkey_handle,
2170 NULL, "MHKM", "vdd", i + 1,
2171 !!(mask & (1 << i)))) {
2172 rc = -EIO;
2173 break;
2174 }
2175 }
2176 }
2177
2178
2179
2180
2181
2182
2183
2184
2185 if (!hotkey_mask_get() && !rc && (fwmask & ~hotkey_acpi_mask)) {
2186 printk(TPACPI_NOTICE
2187 "asked for hotkey mask 0x%08x, but "
2188 "firmware forced it to 0x%08x\n",
2189 fwmask, hotkey_acpi_mask);
2190 }
2191
2192 hotkey_mask_warn_incomplete_mask();
2193
2194 return rc;
2195}
2196
2197
2198
2199
2200
2201
2202static int hotkey_user_mask_set(const u32 mask)
2203{
2204 int rc;
2205
2206
2207
2208 if (!tp_warned.hotkey_mask_ff &&
2209 (mask == 0xffff || mask == 0xffffff ||
2210 mask == 0xffffffff)) {
2211 tp_warned.hotkey_mask_ff = 1;
2212 printk(TPACPI_NOTICE
2213 "setting the hotkey mask to 0x%08x is likely "
2214 "not the best way to go about it\n", mask);
2215 printk(TPACPI_NOTICE
2216 "please consider using the driver defaults, "
2217 "and refer to up-to-date thinkpad-acpi "
2218 "documentation\n");
2219 }
2220
2221
2222
2223 rc = hotkey_mask_set((mask | hotkey_driver_mask) & ~hotkey_source_mask);
2224
2225
2226 hotkey_user_mask = mask & (hotkey_acpi_mask | hotkey_source_mask);
2227
2228 return rc;
2229}
2230
2231
2232
2233
2234
2235
2236static int tpacpi_hotkey_driver_mask_set(const u32 mask)
2237{
2238 int rc;
2239
2240
2241 if (!tp_features.hotkey) {
2242 hotkey_driver_mask = mask;
2243 return 0;
2244 }
2245
2246 mutex_lock(&hotkey_mutex);
2247
2248 HOTKEY_CONFIG_CRITICAL_START
2249 hotkey_driver_mask = mask;
2250#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2251 hotkey_source_mask |= (mask & ~hotkey_all_mask);
2252#endif
2253 HOTKEY_CONFIG_CRITICAL_END
2254
2255 rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) &
2256 ~hotkey_source_mask);
2257 mutex_unlock(&hotkey_mutex);
2258
2259 return rc;
2260}
2261
2262static int hotkey_status_get(int *status)
2263{
2264 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
2265 return -EIO;
2266
2267 return 0;
2268}
2269
2270static int hotkey_status_set(bool enable)
2271{
2272 if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", enable ? 1 : 0))
2273 return -EIO;
2274
2275 return 0;
2276}
2277
2278static void tpacpi_input_send_tabletsw(void)
2279{
2280 int state;
2281
2282 if (tp_features.hotkey_tablet &&
2283 !hotkey_get_tablet_mode(&state)) {
2284 mutex_lock(&tpacpi_inputdev_send_mutex);
2285
2286 input_report_switch(tpacpi_inputdev,
2287 SW_TABLET_MODE, !!state);
2288 input_sync(tpacpi_inputdev);
2289
2290 mutex_unlock(&tpacpi_inputdev_send_mutex);
2291 }
2292}
2293
2294
2295static void tpacpi_input_send_key(const unsigned int scancode)
2296{
2297 const unsigned int keycode = hotkey_keycode_map[scancode];
2298
2299 if (keycode != KEY_RESERVED) {
2300 mutex_lock(&tpacpi_inputdev_send_mutex);
2301
2302 input_report_key(tpacpi_inputdev, keycode, 1);
2303 if (keycode == KEY_UNKNOWN)
2304 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
2305 scancode);
2306 input_sync(tpacpi_inputdev);
2307
2308 input_report_key(tpacpi_inputdev, keycode, 0);
2309 if (keycode == KEY_UNKNOWN)
2310 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
2311 scancode);
2312 input_sync(tpacpi_inputdev);
2313
2314 mutex_unlock(&tpacpi_inputdev_send_mutex);
2315 }
2316}
2317
2318
2319static void tpacpi_input_send_key_masked(const unsigned int scancode)
2320{
2321 hotkey_driver_event(scancode);
2322 if (hotkey_user_mask & (1 << scancode))
2323 tpacpi_input_send_key(scancode);
2324}
2325
2326#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2327static struct tp_acpi_drv_struct ibm_hotkey_acpidriver;
2328
2329
2330static void tpacpi_hotkey_send_key(unsigned int scancode)
2331{
2332 tpacpi_input_send_key_masked(scancode);
2333 if (hotkey_report_mode < 2) {
2334 acpi_bus_generate_proc_event(ibm_hotkey_acpidriver.device,
2335 0x80, TP_HKEY_EV_HOTKEY_BASE + scancode);
2336 }
2337}
2338
2339static void hotkey_read_nvram(struct tp_nvram_state *n, const u32 m)
2340{
2341 u8 d;
2342
2343 if (m & TP_NVRAM_HKEY_GROUP_HK2) {
2344 d = nvram_read_byte(TP_NVRAM_ADDR_HK2);
2345 n->thinkpad_toggle = !!(d & TP_NVRAM_MASK_HKT_THINKPAD);
2346 n->zoom_toggle = !!(d & TP_NVRAM_MASK_HKT_ZOOM);
2347 n->display_toggle = !!(d & TP_NVRAM_MASK_HKT_DISPLAY);
2348 n->hibernate_toggle = !!(d & TP_NVRAM_MASK_HKT_HIBERNATE);
2349 }
2350 if (m & TP_ACPI_HKEY_THNKLGHT_MASK) {
2351 d = nvram_read_byte(TP_NVRAM_ADDR_THINKLIGHT);
2352 n->thinklight_toggle = !!(d & TP_NVRAM_MASK_THINKLIGHT);
2353 }
2354 if (m & TP_ACPI_HKEY_DISPXPAND_MASK) {
2355 d = nvram_read_byte(TP_NVRAM_ADDR_VIDEO);
2356 n->displayexp_toggle =
2357 !!(d & TP_NVRAM_MASK_HKT_DISPEXPND);
2358 }
2359 if (m & TP_NVRAM_HKEY_GROUP_BRIGHTNESS) {
2360 d = nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS);
2361 n->brightness_level = (d & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
2362 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
2363 n->brightness_toggle =
2364 !!(d & TP_NVRAM_MASK_HKT_BRIGHTNESS);
2365 }
2366 if (m & TP_NVRAM_HKEY_GROUP_VOLUME) {
2367 d = nvram_read_byte(TP_NVRAM_ADDR_MIXER);
2368 n->volume_level = (d & TP_NVRAM_MASK_LEVEL_VOLUME)
2369 >> TP_NVRAM_POS_LEVEL_VOLUME;
2370 n->mute = !!(d & TP_NVRAM_MASK_MUTE);
2371 n->volume_toggle = !!(d & TP_NVRAM_MASK_HKT_VOLUME);
2372 }
2373}
2374
2375static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
2376 struct tp_nvram_state *newn,
2377 const u32 event_mask)
2378{
2379
2380#define TPACPI_COMPARE_KEY(__scancode, __member) \
2381 do { \
2382 if ((event_mask & (1 << __scancode)) && \
2383 oldn->__member != newn->__member) \
2384 tpacpi_hotkey_send_key(__scancode); \
2385 } while (0)
2386
2387#define TPACPI_MAY_SEND_KEY(__scancode) \
2388 do { \
2389 if (event_mask & (1 << __scancode)) \
2390 tpacpi_hotkey_send_key(__scancode); \
2391 } while (0)
2392
2393 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle);
2394 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNSPACE, zoom_toggle);
2395 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF7, display_toggle);
2396 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF12, hibernate_toggle);
2397
2398 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNPAGEUP, thinklight_toggle);
2399
2400 TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF8, displayexp_toggle);
2401
2402
2403 if (oldn->volume_toggle != newn->volume_toggle) {
2404 if (oldn->mute != newn->mute) {
2405 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE);
2406 }
2407 if (oldn->volume_level > newn->volume_level) {
2408 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
2409 } else if (oldn->volume_level < newn->volume_level) {
2410 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
2411 } else if (oldn->mute == newn->mute) {
2412
2413 if (newn->mute) {
2414 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE);
2415 } else if (newn->volume_level != 0) {
2416 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
2417 } else {
2418 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
2419 }
2420 }
2421 }
2422
2423
2424 if (oldn->brightness_toggle != newn->brightness_toggle) {
2425 if (oldn->brightness_level < newn->brightness_level) {
2426 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME);
2427 } else if (oldn->brightness_level > newn->brightness_level) {
2428 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND);
2429 } else {
2430
2431 if (newn->brightness_level != 0) {
2432 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME);
2433 } else {
2434 TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND);
2435 }
2436 }
2437 }
2438
2439#undef TPACPI_COMPARE_KEY
2440#undef TPACPI_MAY_SEND_KEY
2441}
2442
2443
2444
2445
2446
2447
2448
2449
2450static int hotkey_kthread(void *data)
2451{
2452 struct tp_nvram_state s[2];
2453 u32 poll_mask, event_mask;
2454 unsigned int si, so;
2455 unsigned long t;
2456 unsigned int change_detector, must_reset;
2457 unsigned int poll_freq;
2458
2459 mutex_lock(&hotkey_thread_mutex);
2460
2461 if (tpacpi_lifecycle == TPACPI_LIFE_EXITING)
2462 goto exit;
2463
2464 set_freezable();
2465
2466 so = 0;
2467 si = 1;
2468 t = 0;
2469
2470
2471 mutex_lock(&hotkey_thread_data_mutex);
2472 change_detector = hotkey_config_change;
2473 poll_mask = hotkey_source_mask;
2474 event_mask = hotkey_source_mask &
2475 (hotkey_driver_mask | hotkey_user_mask);
2476 poll_freq = hotkey_poll_freq;
2477 mutex_unlock(&hotkey_thread_data_mutex);
2478 hotkey_read_nvram(&s[so], poll_mask);
2479
2480 while (!kthread_should_stop()) {
2481 if (t == 0) {
2482 if (likely(poll_freq))
2483 t = 1000/poll_freq;
2484 else
2485 t = 100;
2486 }
2487 t = msleep_interruptible(t);
2488 if (unlikely(kthread_should_stop()))
2489 break;
2490 must_reset = try_to_freeze();
2491 if (t > 0 && !must_reset)
2492 continue;
2493
2494 mutex_lock(&hotkey_thread_data_mutex);
2495 if (must_reset || hotkey_config_change != change_detector) {
2496
2497 si = so;
2498 t = 0;
2499 change_detector = hotkey_config_change;
2500 }
2501 poll_mask = hotkey_source_mask;
2502 event_mask = hotkey_source_mask &
2503 (hotkey_driver_mask | hotkey_user_mask);
2504 poll_freq = hotkey_poll_freq;
2505 mutex_unlock(&hotkey_thread_data_mutex);
2506
2507 if (likely(poll_mask)) {
2508 hotkey_read_nvram(&s[si], poll_mask);
2509 if (likely(si != so)) {
2510 hotkey_compare_and_issue_event(&s[so], &s[si],
2511 event_mask);
2512 }
2513 }
2514
2515 so = si;
2516 si ^= 1;
2517 }
2518
2519exit:
2520 mutex_unlock(&hotkey_thread_mutex);
2521 return 0;
2522}
2523
2524
2525static void hotkey_poll_stop_sync(void)
2526{
2527 if (tpacpi_hotkey_task) {
2528 if (frozen(tpacpi_hotkey_task) ||
2529 freezing(tpacpi_hotkey_task))
2530 thaw_process(tpacpi_hotkey_task);
2531
2532 kthread_stop(tpacpi_hotkey_task);
2533 tpacpi_hotkey_task = NULL;
2534 mutex_lock(&hotkey_thread_mutex);
2535
2536 mutex_unlock(&hotkey_thread_mutex);
2537 }
2538}
2539
2540
2541static void hotkey_poll_setup(bool may_warn)
2542{
2543 const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask;
2544 const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask;
2545
2546 if (hotkey_poll_freq > 0 &&
2547 (poll_driver_mask ||
2548 (poll_user_mask && tpacpi_inputdev->users > 0))) {
2549 if (!tpacpi_hotkey_task) {
2550 tpacpi_hotkey_task = kthread_run(hotkey_kthread,
2551 NULL, TPACPI_NVRAM_KTHREAD_NAME);
2552 if (IS_ERR(tpacpi_hotkey_task)) {
2553 tpacpi_hotkey_task = NULL;
2554 printk(TPACPI_ERR
2555 "could not create kernel thread "
2556 "for hotkey polling\n");
2557 }
2558 }
2559 } else {
2560 hotkey_poll_stop_sync();
2561 if (may_warn && (poll_driver_mask || poll_user_mask) &&
2562 hotkey_poll_freq == 0) {
2563 printk(TPACPI_NOTICE
2564 "hot keys 0x%08x and/or events 0x%08x "
2565 "require polling, which is currently "
2566 "disabled\n",
2567 poll_user_mask, poll_driver_mask);
2568 }
2569 }
2570}
2571
2572static void hotkey_poll_setup_safe(bool may_warn)
2573{
2574 mutex_lock(&hotkey_mutex);
2575 hotkey_poll_setup(may_warn);
2576 mutex_unlock(&hotkey_mutex);
2577}
2578
2579
2580static void hotkey_poll_set_freq(unsigned int freq)
2581{
2582 if (!freq)
2583 hotkey_poll_stop_sync();
2584
2585 hotkey_poll_freq = freq;
2586}
2587
2588#else
2589
2590static void hotkey_poll_setup_safe(bool __unused)
2591{
2592}
2593
2594#endif
2595
2596static int hotkey_inputdev_open(struct input_dev *dev)
2597{
2598 switch (tpacpi_lifecycle) {
2599 case TPACPI_LIFE_INIT:
2600
2601
2602
2603
2604 return 0;
2605 case TPACPI_LIFE_EXITING:
2606 return -EBUSY;
2607 case TPACPI_LIFE_RUNNING:
2608 hotkey_poll_setup_safe(false);
2609 return 0;
2610 }
2611
2612
2613 BUG();
2614 return -EBUSY;
2615}
2616
2617static void hotkey_inputdev_close(struct input_dev *dev)
2618{
2619
2620 if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING &&
2621 !(hotkey_source_mask & hotkey_driver_mask))
2622 hotkey_poll_setup_safe(false);
2623}
2624
2625
2626static ssize_t hotkey_enable_show(struct device *dev,
2627 struct device_attribute *attr,
2628 char *buf)
2629{
2630 int res, status;
2631
2632 printk_deprecated_attribute("hotkey_enable",
2633 "Hotkey reporting is always enabled");
2634
2635 res = hotkey_status_get(&status);
2636 if (res)
2637 return res;
2638
2639 return snprintf(buf, PAGE_SIZE, "%d\n", status);
2640}
2641
2642static ssize_t hotkey_enable_store(struct device *dev,
2643 struct device_attribute *attr,
2644 const char *buf, size_t count)
2645{
2646 unsigned long t;
2647
2648 printk_deprecated_attribute("hotkey_enable",
2649 "Hotkeys can be disabled through hotkey_mask");
2650
2651 if (parse_strtoul(buf, 1, &t))
2652 return -EINVAL;
2653
2654 if (t == 0)
2655 return -EPERM;
2656
2657 return count;
2658}
2659
2660static struct device_attribute dev_attr_hotkey_enable =
2661 __ATTR(hotkey_enable, S_IWUSR | S_IRUGO,
2662 hotkey_enable_show, hotkey_enable_store);
2663
2664
2665static ssize_t hotkey_mask_show(struct device *dev,
2666 struct device_attribute *attr,
2667 char *buf)
2668{
2669 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_user_mask);
2670}
2671
2672static ssize_t hotkey_mask_store(struct device *dev,
2673 struct device_attribute *attr,
2674 const char *buf, size_t count)
2675{
2676 unsigned long t;
2677 int res;
2678
2679 if (parse_strtoul(buf, 0xffffffffUL, &t))
2680 return -EINVAL;
2681
2682 if (mutex_lock_killable(&hotkey_mutex))
2683 return -ERESTARTSYS;
2684
2685 res = hotkey_user_mask_set(t);
2686
2687#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2688 hotkey_poll_setup(true);
2689#endif
2690
2691 mutex_unlock(&hotkey_mutex);
2692
2693 tpacpi_disclose_usertask("hotkey_mask", "set to 0x%08lx\n", t);
2694
2695 return (res) ? res : count;
2696}
2697
2698static struct device_attribute dev_attr_hotkey_mask =
2699 __ATTR(hotkey_mask, S_IWUSR | S_IRUGO,
2700 hotkey_mask_show, hotkey_mask_store);
2701
2702
2703static ssize_t hotkey_bios_enabled_show(struct device *dev,
2704 struct device_attribute *attr,
2705 char *buf)
2706{
2707 return sprintf(buf, "0\n");
2708}
2709
2710static struct device_attribute dev_attr_hotkey_bios_enabled =
2711 __ATTR(hotkey_bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
2712
2713
2714static ssize_t hotkey_bios_mask_show(struct device *dev,
2715 struct device_attribute *attr,
2716 char *buf)
2717{
2718 printk_deprecated_attribute("hotkey_bios_mask",
2719 "This attribute is useless.");
2720 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask);
2721}
2722
2723static struct device_attribute dev_attr_hotkey_bios_mask =
2724 __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
2725
2726
2727static ssize_t hotkey_all_mask_show(struct device *dev,
2728 struct device_attribute *attr,
2729 char *buf)
2730{
2731 return snprintf(buf, PAGE_SIZE, "0x%08x\n",
2732 hotkey_all_mask | hotkey_source_mask);
2733}
2734
2735static struct device_attribute dev_attr_hotkey_all_mask =
2736 __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL);
2737
2738
2739static ssize_t hotkey_recommended_mask_show(struct device *dev,
2740 struct device_attribute *attr,
2741 char *buf)
2742{
2743 return snprintf(buf, PAGE_SIZE, "0x%08x\n",
2744 (hotkey_all_mask | hotkey_source_mask)
2745 & ~hotkey_reserved_mask);
2746}
2747
2748static struct device_attribute dev_attr_hotkey_recommended_mask =
2749 __ATTR(hotkey_recommended_mask, S_IRUGO,
2750 hotkey_recommended_mask_show, NULL);
2751
2752#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2753
2754
2755static ssize_t hotkey_source_mask_show(struct device *dev,
2756 struct device_attribute *attr,
2757 char *buf)
2758{
2759 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_source_mask);
2760}
2761
2762static ssize_t hotkey_source_mask_store(struct device *dev,
2763 struct device_attribute *attr,
2764 const char *buf, size_t count)
2765{
2766 unsigned long t;
2767 u32 r_ev;
2768 int rc;
2769
2770 if (parse_strtoul(buf, 0xffffffffUL, &t) ||
2771 ((t & ~TPACPI_HKEY_NVRAM_KNOWN_MASK) != 0))
2772 return -EINVAL;
2773
2774 if (mutex_lock_killable(&hotkey_mutex))
2775 return -ERESTARTSYS;
2776
2777 HOTKEY_CONFIG_CRITICAL_START
2778 hotkey_source_mask = t;
2779 HOTKEY_CONFIG_CRITICAL_END
2780
2781 rc = hotkey_mask_set((hotkey_user_mask | hotkey_driver_mask) &
2782 ~hotkey_source_mask);
2783 hotkey_poll_setup(true);
2784
2785
2786 r_ev = hotkey_driver_mask & ~(hotkey_acpi_mask & hotkey_all_mask)
2787 & ~hotkey_source_mask & TPACPI_HKEY_NVRAM_KNOWN_MASK;
2788
2789 mutex_unlock(&hotkey_mutex);
2790
2791 if (rc < 0)
2792 printk(TPACPI_ERR "hotkey_source_mask: failed to update the"
2793 "firmware event mask!\n");
2794
2795 if (r_ev)
2796 printk(TPACPI_NOTICE "hotkey_source_mask: "
2797 "some important events were disabled: "
2798 "0x%04x\n", r_ev);
2799
2800 tpacpi_disclose_usertask("hotkey_source_mask", "set to 0x%08lx\n", t);
2801
2802 return (rc < 0) ? rc : count;
2803}
2804
2805static struct device_attribute dev_attr_hotkey_source_mask =
2806 __ATTR(hotkey_source_mask, S_IWUSR | S_IRUGO,
2807 hotkey_source_mask_show, hotkey_source_mask_store);
2808
2809
2810static ssize_t hotkey_poll_freq_show(struct device *dev,
2811 struct device_attribute *attr,
2812 char *buf)
2813{
2814 return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_poll_freq);
2815}
2816
2817static ssize_t hotkey_poll_freq_store(struct device *dev,
2818 struct device_attribute *attr,
2819 const char *buf, size_t count)
2820{
2821 unsigned long t;
2822
2823 if (parse_strtoul(buf, 25, &t))
2824 return -EINVAL;
2825
2826 if (mutex_lock_killable(&hotkey_mutex))
2827 return -ERESTARTSYS;
2828
2829 hotkey_poll_set_freq(t);
2830 hotkey_poll_setup(true);
2831
2832 mutex_unlock(&hotkey_mutex);
2833
2834 tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t);
2835
2836 return count;
2837}
2838
2839static struct device_attribute dev_attr_hotkey_poll_freq =
2840 __ATTR(hotkey_poll_freq, S_IWUSR | S_IRUGO,
2841 hotkey_poll_freq_show, hotkey_poll_freq_store);
2842
2843#endif
2844
2845
2846static ssize_t hotkey_radio_sw_show(struct device *dev,
2847 struct device_attribute *attr,
2848 char *buf)
2849{
2850 int res;
2851 res = hotkey_get_wlsw();
2852 if (res < 0)
2853 return res;
2854
2855
2856 tpacpi_rfk_update_hwblock_state((res == TPACPI_RFK_RADIO_OFF));
2857
2858 return snprintf(buf, PAGE_SIZE, "%d\n",
2859 (res == TPACPI_RFK_RADIO_OFF) ? 0 : 1);
2860}
2861
2862static struct device_attribute dev_attr_hotkey_radio_sw =
2863 __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);
2864
2865static void hotkey_radio_sw_notify_change(void)
2866{
2867 if (tp_features.hotkey_wlsw)
2868 sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
2869 "hotkey_radio_sw");
2870}
2871
2872
2873static ssize_t hotkey_tablet_mode_show(struct device *dev,
2874 struct device_attribute *attr,
2875 char *buf)
2876{
2877 int res, s;
2878 res = hotkey_get_tablet_mode(&s);
2879 if (res < 0)
2880 return res;
2881
2882 return snprintf(buf, PAGE_SIZE, "%d\n", !!s);
2883}
2884
2885static struct device_attribute dev_attr_hotkey_tablet_mode =
2886 __ATTR(hotkey_tablet_mode, S_IRUGO, hotkey_tablet_mode_show, NULL);
2887
2888static void hotkey_tablet_mode_notify_change(void)
2889{
2890 if (tp_features.hotkey_tablet)
2891 sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
2892 "hotkey_tablet_mode");
2893}
2894
2895
2896static ssize_t hotkey_report_mode_show(struct device *dev,
2897 struct device_attribute *attr,
2898 char *buf)
2899{
2900 return snprintf(buf, PAGE_SIZE, "%d\n",
2901 (hotkey_report_mode != 0) ? hotkey_report_mode : 1);
2902}
2903
2904static struct device_attribute dev_attr_hotkey_report_mode =
2905 __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
2906
2907
2908static ssize_t hotkey_wakeup_reason_show(struct device *dev,
2909 struct device_attribute *attr,
2910 char *buf)
2911{
2912 return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_wakeup_reason);
2913}
2914
2915static struct device_attribute dev_attr_hotkey_wakeup_reason =
2916 __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL);
2917
2918static void hotkey_wakeup_reason_notify_change(void)
2919{
2920 sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
2921 "wakeup_reason");
2922}
2923
2924
2925static ssize_t hotkey_wakeup_hotunplug_complete_show(struct device *dev,
2926 struct device_attribute *attr,
2927 char *buf)
2928{
2929 return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_autosleep_ack);
2930}
2931
2932static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete =
2933 __ATTR(wakeup_hotunplug_complete, S_IRUGO,
2934 hotkey_wakeup_hotunplug_complete_show, NULL);
2935
2936static void hotkey_wakeup_hotunplug_complete_notify_change(void)
2937{
2938 sysfs_notify(&tpacpi_pdev->dev.kobj, NULL,
2939 "wakeup_hotunplug_complete");
2940}
2941
2942
2943
2944static struct attribute *hotkey_attributes[] __initdata = {
2945 &dev_attr_hotkey_enable.attr,
2946 &dev_attr_hotkey_bios_enabled.attr,
2947 &dev_attr_hotkey_bios_mask.attr,
2948 &dev_attr_hotkey_report_mode.attr,
2949 &dev_attr_hotkey_wakeup_reason.attr,
2950 &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
2951 &dev_attr_hotkey_mask.attr,
2952 &dev_attr_hotkey_all_mask.attr,
2953 &dev_attr_hotkey_recommended_mask.attr,
2954#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
2955 &dev_attr_hotkey_source_mask.attr,
2956 &dev_attr_hotkey_poll_freq.attr,
2957#endif
2958};
2959
2960
2961
2962
2963static void tpacpi_send_radiosw_update(void)
2964{
2965 int wlsw;
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978 wlsw = hotkey_get_wlsw();
2979
2980
2981 if (wlsw == TPACPI_RFK_RADIO_OFF)
2982 tpacpi_rfk_update_hwblock_state(true);
2983
2984
2985 tpacpi_rfk_update_swstate_all();
2986
2987
2988 if (wlsw == TPACPI_RFK_RADIO_ON)
2989 tpacpi_rfk_update_hwblock_state(false);
2990
2991
2992 if (!(wlsw < 0)) {
2993 mutex_lock(&tpacpi_inputdev_send_mutex);
2994
2995 input_report_switch(tpacpi_inputdev,
2996 SW_RFKILL_ALL, (wlsw > 0));
2997 input_sync(tpacpi_inputdev);
2998
2999 mutex_unlock(&tpacpi_inputdev_send_mutex);
3000 }
3001
3002
3003
3004
3005
3006 hotkey_radio_sw_notify_change();
3007}
3008
3009static void hotkey_exit(void)
3010{
3011#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
3012 mutex_lock(&hotkey_mutex);
3013 hotkey_poll_stop_sync();
3014 mutex_unlock(&hotkey_mutex);
3015#endif
3016
3017 if (hotkey_dev_attributes)
3018 delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
3019
3020 kfree(hotkey_keycode_map);
3021
3022 dbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_HKEY,
3023 "restoring original HKEY status and mask\n");
3024
3025
3026 if (((tp_features.hotkey_mask &&
3027 hotkey_mask_set(hotkey_orig_mask)) |
3028 hotkey_status_set(false)) != 0)
3029 printk(TPACPI_ERR
3030 "failed to restore hot key mask "
3031 "to BIOS defaults\n");
3032}
3033
3034static void __init hotkey_unmap(const unsigned int scancode)
3035{
3036 if (hotkey_keycode_map[scancode] != KEY_RESERVED) {
3037 clear_bit(hotkey_keycode_map[scancode],
3038 tpacpi_inputdev->keybit);
3039 hotkey_keycode_map[scancode] = KEY_RESERVED;
3040 }
3041}
3042
3043
3044
3045
3046
3047
3048#define TPACPI_HK_Q_INIMASK 0x0001
3049
3050static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = {
3051 TPACPI_Q_IBM('I', 'H', TPACPI_HK_Q_INIMASK),
3052 TPACPI_Q_IBM('I', 'N', TPACPI_HK_Q_INIMASK),
3053 TPACPI_Q_IBM('I', 'D', TPACPI_HK_Q_INIMASK),
3054 TPACPI_Q_IBM('I', 'W', TPACPI_HK_Q_INIMASK),
3055 TPACPI_Q_IBM('I', 'V', TPACPI_HK_Q_INIMASK),
3056 TPACPI_Q_IBM('1', '0', TPACPI_HK_Q_INIMASK),
3057 TPACPI_Q_IBM('K', 'U', TPACPI_HK_Q_INIMASK),
3058 TPACPI_Q_IBM('K', 'X', TPACPI_HK_Q_INIMASK),
3059 TPACPI_Q_IBM('K', 'Y', TPACPI_HK_Q_INIMASK),
3060 TPACPI_Q_IBM('1', 'B', TPACPI_HK_Q_INIMASK),
3061 TPACPI_Q_IBM('1', '3', TPACPI_HK_Q_INIMASK),
3062 TPACPI_Q_IBM('1', 'E', TPACPI_HK_Q_INIMASK),
3063 TPACPI_Q_IBM('1', 'C', TPACPI_HK_Q_INIMASK),
3064 TPACPI_Q_IBM('1', 'F', TPACPI_HK_Q_INIMASK),
3065 TPACPI_Q_IBM('I', 'Y', TPACPI_HK_Q_INIMASK),
3066 TPACPI_Q_IBM('K', 'Z', TPACPI_HK_Q_INIMASK),
3067 TPACPI_Q_IBM('1', '6', TPACPI_HK_Q_INIMASK),
3068 TPACPI_Q_IBM('I', 'Z', TPACPI_HK_Q_INIMASK),
3069 TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK),
3070};
3071
3072static int __init hotkey_init(struct ibm_init_struct *iibm)
3073{
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103 static u16 ibm_keycode_map[] __initdata = {
3104
3105 KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP,
3106 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
3107 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
3108
3109
3110 KEY_UNKNOWN,
3111 KEY_UNKNOWN,
3112 KEY_UNKNOWN,
3113
3114
3115 KEY_RESERVED,
3116 KEY_RESERVED,
3117
3118
3119 KEY_RESERVED,
3120
3121 KEY_UNKNOWN,
3122 KEY_ZOOM,
3123
3124
3125
3126
3127 KEY_RESERVED,
3128 KEY_RESERVED,
3129 KEY_RESERVED,
3130
3131 KEY_VENDOR,
3132
3133
3134 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3135 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3136 };
3137 static u16 lenovo_keycode_map[] __initdata = {
3138
3139 KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP,
3140 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
3141 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
3142
3143
3144 KEY_UNKNOWN,
3145 KEY_UNKNOWN,
3146 KEY_UNKNOWN,
3147
3148
3149
3150
3151 KEY_BRIGHTNESSUP,
3152 KEY_BRIGHTNESSDOWN,
3153
3154 KEY_RESERVED,
3155
3156 KEY_UNKNOWN,
3157 KEY_ZOOM,
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170 KEY_RESERVED,
3171 KEY_RESERVED,
3172 KEY_RESERVED,
3173
3174 KEY_VENDOR,
3175
3176
3177 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3178 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3179 };
3180
3181#define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map)
3182#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map)
3183#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0])
3184
3185 int res, i;
3186 int status;
3187 int hkeyv;
3188
3189 unsigned long quirks;
3190
3191 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3192 "initializing hotkey subdriver\n");
3193
3194 BUG_ON(!tpacpi_inputdev);
3195 BUG_ON(tpacpi_inputdev->open != NULL ||
3196 tpacpi_inputdev->close != NULL);
3197
3198 TPACPI_ACPIHANDLE_INIT(hkey);
3199 mutex_init(&hotkey_mutex);
3200
3201#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
3202 mutex_init(&hotkey_thread_mutex);
3203 mutex_init(&hotkey_thread_data_mutex);
3204#endif
3205
3206
3207 tp_features.hotkey = hkey_handle != NULL;
3208
3209 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3210 "hotkeys are %s\n",
3211 str_supported(tp_features.hotkey));
3212
3213 if (!tp_features.hotkey)
3214 return 1;
3215
3216 quirks = tpacpi_check_quirks(tpacpi_hotkey_qtable,
3217 ARRAY_SIZE(tpacpi_hotkey_qtable));
3218
3219 tpacpi_disable_brightness_delay();
3220
3221
3222
3223 hotkey_dev_attributes = create_attr_set(
3224 ARRAY_SIZE(hotkey_attributes) + 2,
3225 NULL);
3226 if (!hotkey_dev_attributes)
3227 return -ENOMEM;
3228 res = add_many_to_attr_set(hotkey_dev_attributes,
3229 hotkey_attributes,
3230 ARRAY_SIZE(hotkey_attributes));
3231 if (res)
3232 goto err_exit;
3233
3234
3235
3236
3237 if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
3238 if ((hkeyv >> 8) != 1) {
3239 printk(TPACPI_ERR "unknown version of the "
3240 "HKEY interface: 0x%x\n", hkeyv);
3241 printk(TPACPI_ERR "please report this to %s\n",
3242 TPACPI_MAIL);
3243 } else {
3244
3245
3246
3247
3248 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3249 "firmware HKEY interface version: 0x%x\n",
3250 hkeyv);
3251
3252
3253 if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
3254 "MHKA", "qd")) {
3255 printk(TPACPI_ERR
3256 "missing MHKA handler, "
3257 "please report this to %s\n",
3258 TPACPI_MAIL);
3259
3260 hotkey_all_mask = 0x080cU;
3261 } else {
3262 tp_features.hotkey_mask = 1;
3263 }
3264 }
3265 }
3266
3267 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3268 "hotkey masks are %s\n",
3269 str_supported(tp_features.hotkey_mask));
3270
3271
3272 if (!tp_features.hotkey_mask && !hotkey_all_mask &&
3273 (quirks & TPACPI_HK_Q_INIMASK))
3274 hotkey_all_mask = 0x080cU;
3275
3276
3277 if (tp_features.hotkey_mask) {
3278
3279
3280 res = hotkey_mask_get();
3281 if (res)
3282 goto err_exit;
3283
3284 hotkey_orig_mask = hotkey_acpi_mask;
3285 } else {
3286 hotkey_orig_mask = hotkey_all_mask;
3287 hotkey_acpi_mask = hotkey_all_mask;
3288 }
3289
3290#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3291 if (dbg_wlswemul) {
3292 tp_features.hotkey_wlsw = 1;
3293 printk(TPACPI_INFO
3294 "radio switch emulation enabled\n");
3295 } else
3296#endif
3297
3298 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
3299 tp_features.hotkey_wlsw = 1;
3300 printk(TPACPI_INFO
3301 "radio switch found; radios are %s\n",
3302 enabled(status, 0));
3303 }
3304 if (tp_features.hotkey_wlsw)
3305 res = add_to_attr_set(hotkey_dev_attributes,
3306 &dev_attr_hotkey_radio_sw.attr);
3307
3308
3309 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
3310 tp_features.hotkey_tablet = 1;
3311 printk(TPACPI_INFO
3312 "possible tablet mode switch found; "
3313 "ThinkPad in %s mode\n",
3314 (status & TP_HOTKEY_TABLET_MASK)?
3315 "tablet" : "laptop");
3316 res = add_to_attr_set(hotkey_dev_attributes,
3317 &dev_attr_hotkey_tablet_mode.attr);
3318 }
3319
3320 if (!res)
3321 res = register_attr_set_with_sysfs(
3322 hotkey_dev_attributes,
3323 &tpacpi_pdev->dev.kobj);
3324 if (res)
3325 goto err_exit;
3326
3327
3328
3329 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
3330 GFP_KERNEL);
3331 if (!hotkey_keycode_map) {
3332 printk(TPACPI_ERR
3333 "failed to allocate memory for key map\n");
3334 res = -ENOMEM;
3335 goto err_exit;
3336 }
3337
3338 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
3339 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3340 "using Lenovo default hot key map\n");
3341 memcpy(hotkey_keycode_map, &lenovo_keycode_map,
3342 TPACPI_HOTKEY_MAP_SIZE);
3343 } else {
3344 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3345 "using IBM default hot key map\n");
3346 memcpy(hotkey_keycode_map, &ibm_keycode_map,
3347 TPACPI_HOTKEY_MAP_SIZE);
3348 }
3349
3350 set_bit(EV_KEY, tpacpi_inputdev->evbit);
3351 set_bit(EV_MSC, tpacpi_inputdev->evbit);
3352 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
3353 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
3354 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
3355 tpacpi_inputdev->keycode = hotkey_keycode_map;
3356 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
3357 if (hotkey_keycode_map[i] != KEY_RESERVED) {
3358 set_bit(hotkey_keycode_map[i],
3359 tpacpi_inputdev->keybit);
3360 } else {
3361 if (i < sizeof(hotkey_reserved_mask)*8)
3362 hotkey_reserved_mask |= 1 << i;
3363 }
3364 }
3365
3366 if (tp_features.hotkey_wlsw) {
3367 set_bit(EV_SW, tpacpi_inputdev->evbit);
3368 set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit);
3369 }
3370 if (tp_features.hotkey_tablet) {
3371 set_bit(EV_SW, tpacpi_inputdev->evbit);
3372 set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
3373 }
3374
3375
3376
3377 if (!tp_features.bright_acpimode)
3378
3379 tpacpi_check_std_acpi_brightness_support();
3380
3381 if (tp_features.bright_acpimode && acpi_video_backlight_support()) {
3382 printk(TPACPI_INFO
3383 "This ThinkPad has standard ACPI backlight "
3384 "brightness control, supported by the ACPI "
3385 "video driver\n");
3386 printk(TPACPI_NOTICE
3387 "Disabling thinkpad-acpi brightness events "
3388 "by default...\n");
3389
3390
3391
3392
3393 hotkey_reserved_mask |=
3394 (1 << TP_ACPI_HOTKEYSCAN_FNHOME)
3395 | (1 << TP_ACPI_HOTKEYSCAN_FNEND);
3396 hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNHOME);
3397 hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNEND);
3398 }
3399
3400#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
3401 hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
3402 & ~hotkey_all_mask
3403 & ~hotkey_reserved_mask;
3404
3405 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3406 "hotkey source mask 0x%08x, polling freq %u\n",
3407 hotkey_source_mask, hotkey_poll_freq);
3408#endif
3409
3410 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3411 "enabling firmware HKEY event interface...\n");
3412 res = hotkey_status_set(true);
3413 if (res) {
3414 hotkey_exit();
3415 return res;
3416 }
3417 res = hotkey_mask_set(((hotkey_all_mask & ~hotkey_reserved_mask)
3418 | hotkey_driver_mask)
3419 & ~hotkey_source_mask);
3420 if (res < 0 && res != -ENXIO) {
3421 hotkey_exit();
3422 return res;
3423 }
3424 hotkey_user_mask = (hotkey_acpi_mask | hotkey_source_mask)
3425 & ~hotkey_reserved_mask;
3426 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3427 "initial masks: user=0x%08x, fw=0x%08x, poll=0x%08x\n",
3428 hotkey_user_mask, hotkey_acpi_mask, hotkey_source_mask);
3429
3430 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3431 "legacy ibm/hotkey event reporting over procfs %s\n",
3432 (hotkey_report_mode < 2) ?
3433 "enabled" : "disabled");
3434
3435 tpacpi_inputdev->open = &hotkey_inputdev_open;
3436 tpacpi_inputdev->close = &hotkey_inputdev_close;
3437
3438 hotkey_poll_setup_safe(true);
3439 tpacpi_send_radiosw_update();
3440 tpacpi_input_send_tabletsw();
3441
3442 return 0;
3443
3444err_exit:
3445 delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
3446 hotkey_dev_attributes = NULL;
3447
3448 return (res < 0)? res : 1;
3449}
3450
3451static bool hotkey_notify_hotkey(const u32 hkey,
3452 bool *send_acpi_ev,
3453 bool *ignore_acpi_ev)
3454{
3455
3456 unsigned int scancode = hkey & 0xfff;
3457 *send_acpi_ev = true;
3458 *ignore_acpi_ev = false;
3459
3460 if (scancode > 0 && scancode < 0x21) {
3461 scancode--;
3462 if (!(hotkey_source_mask & (1 << scancode))) {
3463 tpacpi_input_send_key_masked(scancode);
3464 *send_acpi_ev = false;
3465 } else {
3466 *ignore_acpi_ev = true;
3467 }
3468 return true;
3469 }
3470 return false;
3471}
3472
3473static bool hotkey_notify_wakeup(const u32 hkey,
3474 bool *send_acpi_ev,
3475 bool *ignore_acpi_ev)
3476{
3477
3478 *send_acpi_ev = true;
3479 *ignore_acpi_ev = false;
3480
3481 switch (hkey) {
3482 case TP_HKEY_EV_WKUP_S3_UNDOCK:
3483 case TP_HKEY_EV_WKUP_S4_UNDOCK:
3484 hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
3485 *ignore_acpi_ev = true;
3486 break;
3487
3488 case TP_HKEY_EV_WKUP_S3_BAYEJ:
3489 case TP_HKEY_EV_WKUP_S4_BAYEJ:
3490 hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
3491 *ignore_acpi_ev = true;
3492 break;
3493
3494 case TP_HKEY_EV_WKUP_S3_BATLOW:
3495 case TP_HKEY_EV_WKUP_S4_BATLOW:
3496 printk(TPACPI_ALERT
3497 "EMERGENCY WAKEUP: battery almost empty\n");
3498
3499
3500
3501 break;
3502
3503 default:
3504 return false;
3505 }
3506
3507 if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
3508 printk(TPACPI_INFO
3509 "woke up due to a hot-unplug "
3510 "request...\n");
3511 hotkey_wakeup_reason_notify_change();
3512 }
3513 return true;
3514}
3515
3516static bool hotkey_notify_usrevent(const u32 hkey,
3517 bool *send_acpi_ev,
3518 bool *ignore_acpi_ev)
3519{
3520
3521 *send_acpi_ev = true;
3522 *ignore_acpi_ev = false;
3523
3524 switch (hkey) {
3525 case TP_HKEY_EV_PEN_INSERTED:
3526 case TP_HKEY_EV_PEN_REMOVED:
3527 return true;
3528
3529 case TP_HKEY_EV_TABLET_TABLET:
3530 case TP_HKEY_EV_TABLET_NOTEBOOK:
3531 tpacpi_input_send_tabletsw();
3532 hotkey_tablet_mode_notify_change();
3533 *send_acpi_ev = false;
3534 return true;
3535
3536 case TP_HKEY_EV_LID_CLOSE:
3537 case TP_HKEY_EV_LID_OPEN:
3538 case TP_HKEY_EV_BRGHT_CHANGED:
3539
3540 *ignore_acpi_ev = true;
3541 return true;
3542
3543 default:
3544 return false;
3545 }
3546}
3547
3548static bool hotkey_notify_thermal(const u32 hkey,
3549 bool *send_acpi_ev,
3550 bool *ignore_acpi_ev)
3551{
3552
3553 *send_acpi_ev = true;
3554 *ignore_acpi_ev = false;
3555
3556 switch (hkey) {
3557 case TP_HKEY_EV_ALARM_BAT_HOT:
3558 printk(TPACPI_CRIT
3559 "THERMAL ALARM: battery is too hot!\n");
3560
3561 return true;
3562 case TP_HKEY_EV_ALARM_BAT_XHOT:
3563 printk(TPACPI_ALERT
3564 "THERMAL EMERGENCY: battery is extremely hot!\n");
3565
3566 return true;
3567 case TP_HKEY_EV_ALARM_SENSOR_HOT:
3568 printk(TPACPI_CRIT
3569 "THERMAL ALARM: "
3570 "a sensor reports something is too hot!\n");
3571
3572
3573 return true;
3574 case TP_HKEY_EV_ALARM_SENSOR_XHOT:
3575 printk(TPACPI_ALERT
3576 "THERMAL EMERGENCY: "
3577 "a sensor reports something is extremely hot!\n");
3578
3579 return true;
3580 case TP_HKEY_EV_THM_TABLE_CHANGED:
3581 printk(TPACPI_INFO
3582 "EC reports that Thermal Table has changed\n");
3583
3584
3585 return true;
3586 default:
3587 printk(TPACPI_ALERT
3588 "THERMAL ALERT: unknown thermal alarm received\n");
3589 return false;
3590 }
3591}
3592
3593static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3594{
3595 u32 hkey;
3596 bool send_acpi_ev;
3597 bool ignore_acpi_ev;
3598 bool known_ev;
3599
3600 if (event != 0x80) {
3601 printk(TPACPI_ERR
3602 "unknown HKEY notification event %d\n", event);
3603
3604 acpi_bus_generate_netlink_event(
3605 ibm->acpi->device->pnp.device_class,
3606 dev_name(&ibm->acpi->device->dev),
3607 event, 0);
3608 return;
3609 }
3610
3611 while (1) {
3612 if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
3613 printk(TPACPI_ERR "failed to retrieve HKEY event\n");
3614 return;
3615 }
3616
3617 if (hkey == 0) {
3618
3619 return;
3620 }
3621
3622 send_acpi_ev = true;
3623 ignore_acpi_ev = false;
3624
3625 switch (hkey >> 12) {
3626 case 1:
3627
3628 known_ev = hotkey_notify_hotkey(hkey, &send_acpi_ev,
3629 &ignore_acpi_ev);
3630 break;
3631 case 2:
3632
3633 known_ev = hotkey_notify_wakeup(hkey, &send_acpi_ev,
3634 &ignore_acpi_ev);
3635 break;
3636 case 3:
3637
3638 if (hkey == TP_HKEY_EV_BAYEJ_ACK) {
3639 hotkey_autosleep_ack = 1;
3640 printk(TPACPI_INFO
3641 "bay ejected\n");
3642 hotkey_wakeup_hotunplug_complete_notify_change();
3643 known_ev = true;
3644 } else {
3645 known_ev = false;
3646 }
3647 break;
3648 case 4:
3649
3650 if (hkey == TP_HKEY_EV_UNDOCK_ACK) {
3651 hotkey_autosleep_ack = 1;
3652 printk(TPACPI_INFO
3653 "undocked\n");
3654 hotkey_wakeup_hotunplug_complete_notify_change();
3655 known_ev = true;
3656 } else {
3657 known_ev = false;
3658 }
3659 break;
3660 case 5:
3661
3662 known_ev = hotkey_notify_usrevent(hkey, &send_acpi_ev,
3663 &ignore_acpi_ev);
3664 break;
3665 case 6:
3666
3667 known_ev = hotkey_notify_thermal(hkey, &send_acpi_ev,
3668 &ignore_acpi_ev);
3669 break;
3670 case 7:
3671
3672 if (tp_features.hotkey_wlsw &&
3673 hkey == TP_HKEY_EV_RFKILL_CHANGED) {
3674 tpacpi_send_radiosw_update();
3675 send_acpi_ev = 0;
3676 known_ev = true;
3677 break;
3678 }
3679
3680 default:
3681 known_ev = false;
3682 }
3683 if (!known_ev) {
3684 printk(TPACPI_NOTICE
3685 "unhandled HKEY event 0x%04x\n", hkey);
3686 printk(TPACPI_NOTICE
3687 "please report the conditions when this "
3688 "event happened to %s\n", TPACPI_MAIL);
3689 }
3690
3691
3692 if (!ignore_acpi_ev &&
3693 (send_acpi_ev || hotkey_report_mode < 2)) {
3694 acpi_bus_generate_proc_event(ibm->acpi->device,
3695 event, hkey);
3696 }
3697
3698
3699 if (!ignore_acpi_ev && send_acpi_ev) {
3700 acpi_bus_generate_netlink_event(
3701 ibm->acpi->device->pnp.device_class,
3702 dev_name(&ibm->acpi->device->dev),
3703 event, hkey);
3704 }
3705 }
3706}
3707
3708static void hotkey_suspend(pm_message_t state)
3709{
3710
3711 hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE;
3712 hotkey_autosleep_ack = 0;
3713}
3714
3715static void hotkey_resume(void)
3716{
3717 tpacpi_disable_brightness_delay();
3718
3719 if (hotkey_status_set(true) < 0 ||
3720 hotkey_mask_set(hotkey_acpi_mask) < 0)
3721 printk(TPACPI_ERR
3722 "error while attempting to reset the event "
3723 "firmware interface\n");
3724
3725 tpacpi_send_radiosw_update();
3726 hotkey_tablet_mode_notify_change();
3727 hotkey_wakeup_reason_notify_change();
3728 hotkey_wakeup_hotunplug_complete_notify_change();
3729 hotkey_poll_setup_safe(false);
3730}
3731
3732
3733static int hotkey_read(char *p)
3734{
3735 int res, status;
3736 int len = 0;
3737
3738 if (!tp_features.hotkey) {
3739 len += sprintf(p + len, "status:\t\tnot supported\n");
3740 return len;
3741 }
3742
3743 if (mutex_lock_killable(&hotkey_mutex))
3744 return -ERESTARTSYS;
3745 res = hotkey_status_get(&status);
3746 if (!res)
3747 res = hotkey_mask_get();
3748 mutex_unlock(&hotkey_mutex);
3749 if (res)
3750 return res;
3751
3752 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
3753 if (hotkey_all_mask) {
3754 len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_user_mask);
3755 len += sprintf(p + len,
3756 "commands:\tenable, disable, reset, <mask>\n");
3757 } else {
3758 len += sprintf(p + len, "mask:\t\tnot supported\n");
3759 len += sprintf(p + len, "commands:\tenable, disable, reset\n");
3760 }
3761
3762 return len;
3763}
3764
3765static void hotkey_enabledisable_warn(bool enable)
3766{
3767 tpacpi_log_usertask("procfs hotkey enable/disable");
3768 if (!WARN((tpacpi_lifecycle == TPACPI_LIFE_RUNNING || !enable),
3769 TPACPI_WARN
3770 "hotkey enable/disable functionality has been "
3771 "removed from the driver. Hotkeys are always "
3772 "enabled\n"))
3773 printk(TPACPI_ERR
3774 "Please remove the hotkey=enable module "
3775 "parameter, it is deprecated. Hotkeys are always "
3776 "enabled\n");
3777}
3778
3779static int hotkey_write(char *buf)
3780{
3781 int res;
3782 u32 mask;
3783 char *cmd;
3784
3785 if (!tp_features.hotkey)
3786 return -ENODEV;
3787
3788 if (mutex_lock_killable(&hotkey_mutex))
3789 return -ERESTARTSYS;
3790
3791 mask = hotkey_user_mask;
3792
3793 res = 0;
3794 while ((cmd = next_cmd(&buf))) {
3795 if (strlencmp(cmd, "enable") == 0) {
3796 hotkey_enabledisable_warn(1);
3797 } else if (strlencmp(cmd, "disable") == 0) {
3798 hotkey_enabledisable_warn(0);
3799 res = -EPERM;
3800 } else if (strlencmp(cmd, "reset") == 0) {
3801 mask = (hotkey_all_mask | hotkey_source_mask)
3802 & ~hotkey_reserved_mask;
3803 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
3804
3805 } else if (sscanf(cmd, "%x", &mask) == 1) {
3806
3807 } else {
3808 res = -EINVAL;
3809 goto errexit;
3810 }
3811 }
3812
3813 if (!res) {
3814 tpacpi_disclose_usertask("procfs hotkey",
3815 "set mask to 0x%08x\n", mask);
3816 res = hotkey_user_mask_set(mask);
3817 }
3818
3819errexit:
3820 mutex_unlock(&hotkey_mutex);
3821 return res;
3822}
3823
3824static const struct acpi_device_id ibm_htk_device_ids[] = {
3825 {TPACPI_ACPI_HKEY_HID, 0},
3826 {"", 0},
3827};
3828
3829static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = {
3830 .hid = ibm_htk_device_ids,
3831 .notify = hotkey_notify,
3832 .handle = &hkey_handle,
3833 .type = ACPI_DEVICE_NOTIFY,
3834};
3835
3836static struct ibm_struct hotkey_driver_data = {
3837 .name = "hotkey",
3838 .read = hotkey_read,
3839 .write = hotkey_write,
3840 .exit = hotkey_exit,
3841 .resume = hotkey_resume,
3842 .suspend = hotkey_suspend,
3843 .acpi = &ibm_hotkey_acpidriver,
3844};
3845
3846
3847
3848
3849
3850enum {
3851
3852 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01,
3853 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02,
3854 TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04,
3855
3856};
3857
3858enum {
3859
3860 TP_ACPI_BLTH_GET_ULTRAPORT_ID = 0x00,
3861 TP_ACPI_BLTH_GET_PWR_ON_RESUME = 0x01,
3862 TP_ACPI_BLTH_PWR_ON_ON_RESUME = 0x02,
3863 TP_ACPI_BLTH_PWR_OFF_ON_RESUME = 0x03,
3864 TP_ACPI_BLTH_SAVE_STATE = 0x05,
3865};
3866
3867#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw"
3868
3869static void bluetooth_suspend(pm_message_t state)
3870{
3871
3872 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
3873 TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
3874 vdbg_printk(TPACPI_DBG_RFKILL,
3875 "bluetooth power down on resume request failed\n");
3876}
3877
3878static int bluetooth_get_status(void)
3879{
3880 int status;
3881
3882#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3883 if (dbg_bluetoothemul)
3884 return (tpacpi_bluetooth_emulstate) ?
3885 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
3886#endif
3887
3888 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
3889 return -EIO;
3890
3891 return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0) ?
3892 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
3893}
3894
3895static int bluetooth_set_status(enum tpacpi_rfkill_state state)
3896{
3897 int status;
3898
3899 vdbg_printk(TPACPI_DBG_RFKILL,
3900 "will attempt to %s bluetooth\n",
3901 (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable");
3902
3903#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3904 if (dbg_bluetoothemul) {
3905 tpacpi_bluetooth_emulstate = (state == TPACPI_RFK_RADIO_ON);
3906 return 0;
3907 }
3908#endif
3909
3910
3911 if (state == TPACPI_RFK_RADIO_ON)
3912 status = TP_ACPI_BLUETOOTH_RADIOSSW;
3913 else
3914 status = 0;
3915
3916 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
3917 return -EIO;
3918
3919 return 0;
3920}
3921
3922
3923static ssize_t bluetooth_enable_show(struct device *dev,
3924 struct device_attribute *attr,
3925 char *buf)
3926{
3927 return tpacpi_rfk_sysfs_enable_show(TPACPI_RFK_BLUETOOTH_SW_ID,
3928 attr, buf);
3929}
3930
3931static ssize_t bluetooth_enable_store(struct device *dev,
3932 struct device_attribute *attr,
3933 const char *buf, size_t count)
3934{
3935 return tpacpi_rfk_sysfs_enable_store(TPACPI_RFK_BLUETOOTH_SW_ID,
3936 attr, buf, count);
3937}
3938
3939static struct device_attribute dev_attr_bluetooth_enable =
3940 __ATTR(bluetooth_enable, S_IWUSR | S_IRUGO,
3941 bluetooth_enable_show, bluetooth_enable_store);
3942
3943
3944
3945static struct attribute *bluetooth_attributes[] = {
3946 &dev_attr_bluetooth_enable.attr,
3947 NULL
3948};
3949
3950static const struct attribute_group bluetooth_attr_group = {
3951 .attrs = bluetooth_attributes,
3952};
3953
3954static const struct tpacpi_rfk_ops bluetooth_tprfk_ops = {
3955 .get_status = bluetooth_get_status,
3956 .set_status = bluetooth_set_status,
3957};
3958
3959static void bluetooth_shutdown(void)
3960{
3961
3962 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
3963 TP_ACPI_BLTH_SAVE_STATE))
3964 printk(TPACPI_NOTICE
3965 "failed to save bluetooth state to NVRAM\n");
3966 else
3967 vdbg_printk(TPACPI_DBG_RFKILL,
3968 "bluestooth state saved to NVRAM\n");
3969}
3970
3971static void bluetooth_exit(void)
3972{
3973 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
3974 &bluetooth_attr_group);
3975
3976 tpacpi_destroy_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID);
3977
3978 bluetooth_shutdown();
3979}
3980
3981static int __init bluetooth_init(struct ibm_init_struct *iibm)
3982{
3983 int res;
3984 int status = 0;
3985
3986 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3987 "initializing bluetooth subdriver\n");
3988
3989 TPACPI_ACPIHANDLE_INIT(hkey);
3990
3991
3992
3993 tp_features.bluetooth = hkey_handle &&
3994 acpi_evalf(hkey_handle, &status, "GBDC", "qd");
3995
3996 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3997 "bluetooth is %s, status 0x%02x\n",
3998 str_supported(tp_features.bluetooth),
3999 status);
4000
4001#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4002 if (dbg_bluetoothemul) {
4003 tp_features.bluetooth = 1;
4004 printk(TPACPI_INFO
4005 "bluetooth switch emulation enabled\n");
4006 } else
4007#endif
4008 if (tp_features.bluetooth &&
4009 !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
4010
4011 tp_features.bluetooth = 0;
4012 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
4013 "bluetooth hardware not installed\n");
4014 }
4015
4016 if (!tp_features.bluetooth)
4017 return 1;
4018
4019 res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID,
4020 &bluetooth_tprfk_ops,
4021 RFKILL_TYPE_BLUETOOTH,
4022 TPACPI_RFK_BLUETOOTH_SW_NAME,
4023 true);
4024 if (res)
4025 return res;
4026
4027 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
4028 &bluetooth_attr_group);
4029 if (res) {
4030 tpacpi_destroy_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID);
4031 return res;
4032 }
4033
4034 return 0;
4035}
4036
4037
4038static int bluetooth_read(char *p)
4039{
4040 return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p);
4041}
4042
4043static int bluetooth_write(char *buf)
4044{
4045 return tpacpi_rfk_procfs_write(TPACPI_RFK_BLUETOOTH_SW_ID, buf);
4046}
4047
4048static struct ibm_struct bluetooth_driver_data = {
4049 .name = "bluetooth",
4050 .read = bluetooth_read,
4051 .write = bluetooth_write,
4052 .exit = bluetooth_exit,
4053 .suspend = bluetooth_suspend,
4054 .shutdown = bluetooth_shutdown,
4055};
4056
4057
4058
4059
4060
4061enum {
4062
4063 TP_ACPI_WANCARD_HWPRESENT = 0x01,
4064 TP_ACPI_WANCARD_RADIOSSW = 0x02,
4065 TP_ACPI_WANCARD_RESUMECTRL = 0x04,
4066
4067};
4068
4069#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
4070
4071static void wan_suspend(pm_message_t state)
4072{
4073
4074 if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
4075 TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
4076 vdbg_printk(TPACPI_DBG_RFKILL,
4077 "WWAN power down on resume request failed\n");
4078}
4079
4080static int wan_get_status(void)
4081{
4082 int status;
4083
4084#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4085 if (dbg_wwanemul)
4086 return (tpacpi_wwan_emulstate) ?
4087 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
4088#endif
4089
4090 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
4091 return -EIO;
4092
4093 return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0) ?
4094 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
4095}
4096
4097static int wan_set_status(enum tpacpi_rfkill_state state)
4098{
4099 int status;
4100
4101 vdbg_printk(TPACPI_DBG_RFKILL,
4102 "will attempt to %s wwan\n",
4103 (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable");
4104
4105#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4106 if (dbg_wwanemul) {
4107 tpacpi_wwan_emulstate = (state == TPACPI_RFK_RADIO_ON);
4108 return 0;
4109 }
4110#endif
4111
4112
4113 if (state == TPACPI_RFK_RADIO_ON)
4114 status = TP_ACPI_WANCARD_RADIOSSW;
4115 else
4116 status = 0;
4117
4118 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
4119 return -EIO;
4120
4121 return 0;
4122}
4123
4124
4125static ssize_t wan_enable_show(struct device *dev,
4126 struct device_attribute *attr,
4127 char *buf)
4128{
4129 return tpacpi_rfk_sysfs_enable_show(TPACPI_RFK_WWAN_SW_ID,
4130 attr, buf);
4131}
4132
4133static ssize_t wan_enable_store(struct device *dev,
4134 struct device_attribute *attr,
4135 const char *buf, size_t count)
4136{
4137 return tpacpi_rfk_sysfs_enable_store(TPACPI_RFK_WWAN_SW_ID,
4138 attr, buf, count);
4139}
4140
4141static struct device_attribute dev_attr_wan_enable =
4142 __ATTR(wwan_enable, S_IWUSR | S_IRUGO,
4143 wan_enable_show, wan_enable_store);
4144
4145
4146
4147static struct attribute *wan_attributes[] = {
4148 &dev_attr_wan_enable.attr,
4149 NULL
4150};
4151
4152static const struct attribute_group wan_attr_group = {
4153 .attrs = wan_attributes,
4154};
4155
4156static const struct tpacpi_rfk_ops wan_tprfk_ops = {
4157 .get_status = wan_get_status,
4158 .set_status = wan_set_status,
4159};
4160
4161static void wan_shutdown(void)
4162{
4163
4164 if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd",
4165 TP_ACPI_WGSV_SAVE_STATE))
4166 printk(TPACPI_NOTICE
4167 "failed to save WWAN state to NVRAM\n");
4168 else
4169 vdbg_printk(TPACPI_DBG_RFKILL,
4170 "WWAN state saved to NVRAM\n");
4171}
4172
4173static void wan_exit(void)
4174{
4175 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
4176 &wan_attr_group);
4177
4178 tpacpi_destroy_rfkill(TPACPI_RFK_WWAN_SW_ID);
4179
4180 wan_shutdown();
4181}
4182
4183static int __init wan_init(struct ibm_init_struct *iibm)
4184{
4185 int res;
4186 int status = 0;
4187
4188 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
4189 "initializing wan subdriver\n");
4190
4191 TPACPI_ACPIHANDLE_INIT(hkey);
4192
4193 tp_features.wan = hkey_handle &&
4194 acpi_evalf(hkey_handle, &status, "GWAN", "qd");
4195
4196 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
4197 "wan is %s, status 0x%02x\n",
4198 str_supported(tp_features.wan),
4199 status);
4200
4201#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4202 if (dbg_wwanemul) {
4203 tp_features.wan = 1;
4204 printk(TPACPI_INFO
4205 "wwan switch emulation enabled\n");
4206 } else
4207#endif
4208 if (tp_features.wan &&
4209 !(status & TP_ACPI_WANCARD_HWPRESENT)) {
4210
4211 tp_features.wan = 0;
4212 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
4213 "wan hardware not installed\n");
4214 }
4215
4216 if (!tp_features.wan)
4217 return 1;
4218
4219 res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID,
4220 &wan_tprfk_ops,
4221 RFKILL_TYPE_WWAN,
4222 TPACPI_RFK_WWAN_SW_NAME,
4223 true);
4224 if (res)
4225 return res;
4226
4227 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
4228 &wan_attr_group);
4229
4230 if (res) {
4231 tpacpi_destroy_rfkill(TPACPI_RFK_WWAN_SW_ID);
4232 return res;
4233 }
4234
4235 return 0;
4236}
4237
4238
4239static int wan_read(char *p)
4240{
4241 return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p);
4242}
4243
4244static int wan_write(char *buf)
4245{
4246 return tpacpi_rfk_procfs_write(TPACPI_RFK_WWAN_SW_ID, buf);
4247}
4248
4249static struct ibm_struct wan_driver_data = {
4250 .name = "wan",
4251 .read = wan_read,
4252 .write = wan_write,
4253 .exit = wan_exit,
4254 .suspend = wan_suspend,
4255 .shutdown = wan_shutdown,
4256};
4257
4258
4259
4260
4261
4262enum {
4263
4264 TP_ACPI_UWB_HWPRESENT = 0x01,
4265 TP_ACPI_UWB_RADIOSSW = 0x02,
4266};
4267
4268#define TPACPI_RFK_UWB_SW_NAME "tpacpi_uwb_sw"
4269
4270static int uwb_get_status(void)
4271{
4272 int status;
4273
4274#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4275 if (dbg_uwbemul)
4276 return (tpacpi_uwb_emulstate) ?
4277 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
4278#endif
4279
4280 if (!acpi_evalf(hkey_handle, &status, "GUWB", "d"))
4281 return -EIO;
4282
4283 return ((status & TP_ACPI_UWB_RADIOSSW) != 0) ?
4284 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
4285}
4286
4287static int uwb_set_status(enum tpacpi_rfkill_state state)
4288{
4289 int status;
4290
4291 vdbg_printk(TPACPI_DBG_RFKILL,
4292 "will attempt to %s UWB\n",
4293 (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable");
4294
4295#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4296 if (dbg_uwbemul) {
4297 tpacpi_uwb_emulstate = (state == TPACPI_RFK_RADIO_ON);
4298 return 0;
4299 }
4300#endif
4301
4302 if (state == TPACPI_RFK_RADIO_ON)
4303 status = TP_ACPI_UWB_RADIOSSW;
4304 else
4305 status = 0;
4306
4307 if (!acpi_evalf(hkey_handle, NULL, "SUWB", "vd", status))
4308 return -EIO;
4309
4310 return 0;
4311}
4312
4313
4314
4315static const struct tpacpi_rfk_ops uwb_tprfk_ops = {
4316 .get_status = uwb_get_status,
4317 .set_status = uwb_set_status,
4318};
4319
4320static void uwb_exit(void)
4321{
4322 tpacpi_destroy_rfkill(TPACPI_RFK_UWB_SW_ID);
4323}
4324
4325static int __init uwb_init(struct ibm_init_struct *iibm)
4326{
4327 int res;
4328 int status = 0;
4329
4330 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
4331 "initializing uwb subdriver\n");
4332
4333 TPACPI_ACPIHANDLE_INIT(hkey);
4334
4335 tp_features.uwb = hkey_handle &&
4336 acpi_evalf(hkey_handle, &status, "GUWB", "qd");
4337
4338 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
4339 "uwb is %s, status 0x%02x\n",
4340 str_supported(tp_features.uwb),
4341 status);
4342
4343#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4344 if (dbg_uwbemul) {
4345 tp_features.uwb = 1;
4346 printk(TPACPI_INFO
4347 "uwb switch emulation enabled\n");
4348 } else
4349#endif
4350 if (tp_features.uwb &&
4351 !(status & TP_ACPI_UWB_HWPRESENT)) {
4352
4353 tp_features.uwb = 0;
4354 dbg_printk(TPACPI_DBG_INIT,
4355 "uwb hardware not installed\n");
4356 }
4357
4358 if (!tp_features.uwb)
4359 return 1;
4360
4361 res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID,
4362 &uwb_tprfk_ops,
4363 RFKILL_TYPE_UWB,
4364 TPACPI_RFK_UWB_SW_NAME,
4365 false);
4366 return res;
4367}
4368
4369static struct ibm_struct uwb_driver_data = {
4370 .name = "uwb",
4371 .exit = uwb_exit,
4372 .flags.experimental = 1,
4373};
4374
4375
4376
4377
4378
4379#ifdef CONFIG_THINKPAD_ACPI_VIDEO
4380
4381enum video_access_mode {
4382 TPACPI_VIDEO_NONE = 0,
4383 TPACPI_VIDEO_570,
4384 TPACPI_VIDEO_770,
4385 TPACPI_VIDEO_NEW,
4386};
4387
4388enum {
4389 TP_ACPI_VIDEO_S_LCD = 0x01,
4390 TP_ACPI_VIDEO_S_CRT = 0x02,
4391 TP_ACPI_VIDEO_S_DVI = 0x08,
4392};
4393
4394enum {
4395 TP_ACPI_VIDEO_570_PHSCMD = 0x87,
4396 TP_ACPI_VIDEO_570_PHSMASK = 0x03,
4397
4398 TP_ACPI_VIDEO_570_PHS2CMD = 0x8b,
4399 TP_ACPI_VIDEO_570_PHS2SET = 0x80,
4400};
4401
4402static enum video_access_mode video_supported;
4403static int video_orig_autosw;
4404
4405static int video_autosw_get(void);
4406static int video_autosw_set(int enable);
4407
4408TPACPI_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID");
4409
4410static int __init video_init(struct ibm_init_struct *iibm)
4411{
4412 int ivga;
4413
4414 vdbg_printk(TPACPI_DBG_INIT, "initializing video subdriver\n");
4415
4416 TPACPI_ACPIHANDLE_INIT(vid);
4417 TPACPI_ACPIHANDLE_INIT(vid2);
4418
4419 if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
4420
4421 vid_handle = vid2_handle;
4422
4423 if (!vid_handle)
4424
4425 video_supported = TPACPI_VIDEO_NONE;
4426 else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
4427
4428 video_supported = TPACPI_VIDEO_570;
4429 else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
4430
4431 video_supported = TPACPI_VIDEO_770;
4432 else
4433
4434 video_supported = TPACPI_VIDEO_NEW;
4435
4436 vdbg_printk(TPACPI_DBG_INIT, "video is %s, mode %d\n",
4437 str_supported(video_supported != TPACPI_VIDEO_NONE),
4438 video_supported);
4439
4440 return (video_supported != TPACPI_VIDEO_NONE)? 0 : 1;
4441}
4442
4443static void video_exit(void)
4444{
4445 dbg_printk(TPACPI_DBG_EXIT,
4446 "restoring original video autoswitch mode\n");
4447 if (video_autosw_set(video_orig_autosw))
4448 printk(TPACPI_ERR "error while trying to restore original "
4449 "video autoswitch mode\n");
4450}
4451
4452static int video_outputsw_get(void)
4453{
4454 int status = 0;
4455 int i;
4456
4457 switch (video_supported) {
4458 case TPACPI_VIDEO_570:
4459 if (!acpi_evalf(NULL, &i, "\\_SB.PHS", "dd",
4460 TP_ACPI_VIDEO_570_PHSCMD))
4461 return -EIO;
4462 status = i & TP_ACPI_VIDEO_570_PHSMASK;
4463 break;
4464 case TPACPI_VIDEO_770:
4465 if (!acpi_evalf(NULL, &i, "\\VCDL", "d"))
4466 return -EIO;
4467 if (i)
4468 status |= TP_ACPI_VIDEO_S_LCD;
4469 if (!acpi_evalf(NULL, &i, "\\VCDC", "d"))
4470 return -EIO;
4471 if (i)
4472 status |= TP_ACPI_VIDEO_S_CRT;
4473 break;
4474 case TPACPI_VIDEO_NEW:
4475 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1) ||
4476 !acpi_evalf(NULL, &i, "\\VCDC", "d"))
4477 return -EIO;
4478 if (i)
4479 status |= TP_ACPI_VIDEO_S_CRT;
4480
4481 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0) ||
4482 !acpi_evalf(NULL, &i, "\\VCDL", "d"))
4483 return -EIO;
4484 if (i)
4485 status |= TP_ACPI_VIDEO_S_LCD;
4486 if (!acpi_evalf(NULL, &i, "\\VCDD", "d"))
4487 return -EIO;
4488 if (i)
4489 status |= TP_ACPI_VIDEO_S_DVI;
4490 break;
4491 default:
4492 return -ENOSYS;
4493 }
4494
4495 return status;
4496}
4497
4498static int video_outputsw_set(int status)
4499{
4500 int autosw;
4501 int res = 0;
4502
4503 switch (video_supported) {
4504 case TPACPI_VIDEO_570:
4505 res = acpi_evalf(NULL, NULL,
4506 "\\_SB.PHS2", "vdd",
4507 TP_ACPI_VIDEO_570_PHS2CMD,
4508 status | TP_ACPI_VIDEO_570_PHS2SET);
4509 break;
4510 case TPACPI_VIDEO_770:
4511 autosw = video_autosw_get();
4512 if (autosw < 0)
4513 return autosw;
4514
4515 res = video_autosw_set(1);
4516 if (res)
4517 return res;
4518 res = acpi_evalf(vid_handle, NULL,
4519 "ASWT", "vdd", status * 0x100, 0);
4520 if (!autosw && video_autosw_set(autosw)) {
4521 printk(TPACPI_ERR
4522 "video auto-switch left enabled due to error\n");
4523 return -EIO;
4524 }
4525 break;
4526 case TPACPI_VIDEO_NEW:
4527 res = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
4528 acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
4529 break;
4530 default:
4531 return -ENOSYS;
4532 }
4533
4534 return (res)? 0 : -EIO;
4535}
4536
4537static int video_autosw_get(void)
4538{
4539 int autosw = 0;
4540
4541 switch (video_supported) {
4542 case TPACPI_VIDEO_570:
4543 if (!acpi_evalf(vid_handle, &autosw, "SWIT", "d"))
4544 return -EIO;
4545 break;
4546 case TPACPI_VIDEO_770:
4547 case TPACPI_VIDEO_NEW:
4548 if (!acpi_evalf(vid_handle, &autosw, "^VDEE", "d"))
4549 return -EIO;
4550 break;
4551 default:
4552 return -ENOSYS;
4553 }
4554
4555 return autosw & 1;
4556}
4557
4558static int video_autosw_set(int enable)
4559{
4560 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable)? 1 : 0))
4561 return -EIO;
4562 return 0;
4563}
4564
4565static int video_outputsw_cycle(void)
4566{
4567 int autosw = video_autosw_get();
4568 int res;
4569
4570 if (autosw < 0)
4571 return autosw;
4572
4573 switch (video_supported) {
4574 case TPACPI_VIDEO_570:
4575 res = video_autosw_set(1);
4576 if (res)
4577 return res;
4578 res = acpi_evalf(ec_handle, NULL, "_Q16", "v");
4579 break;
4580 case TPACPI_VIDEO_770:
4581 case TPACPI_VIDEO_NEW:
4582 res = video_autosw_set(1);
4583 if (res)
4584 return res;
4585 res = acpi_evalf(vid_handle, NULL, "VSWT", "v");
4586 break;
4587 default:
4588 return -ENOSYS;
4589 }
4590 if (!autosw && video_autosw_set(autosw)) {
4591 printk(TPACPI_ERR
4592 "video auto-switch left enabled due to error\n");
4593 return -EIO;
4594 }
4595
4596 return (res)? 0 : -EIO;
4597}
4598
4599static int video_expand_toggle(void)
4600{
4601 switch (video_supported) {
4602 case TPACPI_VIDEO_570:
4603 return acpi_evalf(ec_handle, NULL, "_Q17", "v")?
4604 0 : -EIO;
4605 case TPACPI_VIDEO_770:
4606 return acpi_evalf(vid_handle, NULL, "VEXP", "v")?
4607 0 : -EIO;
4608 case TPACPI_VIDEO_NEW:
4609 return acpi_evalf(NULL, NULL, "\\VEXP", "v")?
4610 0 : -EIO;
4611 default:
4612 return -ENOSYS;
4613 }
4614
4615}
4616
4617static int video_read(char *p)
4618{
4619 int status, autosw;
4620 int len = 0;
4621
4622 if (video_supported == TPACPI_VIDEO_NONE) {
4623 len += sprintf(p + len, "status:\t\tnot supported\n");
4624 return len;
4625 }
4626
4627 status = video_outputsw_get();
4628 if (status < 0)
4629 return status;
4630
4631 autosw = video_autosw_get();
4632 if (autosw < 0)
4633 return autosw;
4634
4635 len += sprintf(p + len, "status:\t\tsupported\n");
4636 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
4637 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
4638 if (video_supported == TPACPI_VIDEO_NEW)
4639 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
4640 len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
4641 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
4642 len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
4643 if (video_supported == TPACPI_VIDEO_NEW)
4644 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
4645 len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
4646 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
4647
4648 return len;
4649}
4650
4651static int video_write(char *buf)
4652{
4653 char *cmd;
4654 int enable, disable, status;
4655 int res;
4656
4657 if (video_supported == TPACPI_VIDEO_NONE)
4658 return -ENODEV;
4659
4660 enable = 0;
4661 disable = 0;
4662
4663 while ((cmd = next_cmd(&buf))) {
4664 if (strlencmp(cmd, "lcd_enable") == 0) {
4665 enable |= TP_ACPI_VIDEO_S_LCD;
4666 } else if (strlencmp(cmd, "lcd_disable") == 0) {
4667 disable |= TP_ACPI_VIDEO_S_LCD;
4668 } else if (strlencmp(cmd, "crt_enable") == 0) {
4669 enable |= TP_ACPI_VIDEO_S_CRT;
4670 } else if (strlencmp(cmd, "crt_disable") == 0) {
4671 disable |= TP_ACPI_VIDEO_S_CRT;
4672 } else if (video_supported == TPACPI_VIDEO_NEW &&
4673 strlencmp(cmd, "dvi_enable") == 0) {
4674 enable |= TP_ACPI_VIDEO_S_DVI;
4675 } else if (video_supported == TPACPI_VIDEO_NEW &&
4676 strlencmp(cmd, "dvi_disable") == 0) {
4677 disable |= TP_ACPI_VIDEO_S_DVI;
4678 } else if (strlencmp(cmd, "auto_enable") == 0) {
4679 res = video_autosw_set(1);
4680 if (res)
4681 return res;
4682 } else if (strlencmp(cmd, "auto_disable") == 0) {
4683 res = video_autosw_set(0);
4684 if (res)
4685 return res;
4686 } else if (strlencmp(cmd, "video_switch") == 0) {
4687 res = video_outputsw_cycle();
4688 if (res)
4689 return res;
4690 } else if (strlencmp(cmd, "expand_toggle") == 0) {
4691 res = video_expand_toggle();
4692 if (res)
4693 return res;
4694 } else
4695 return -EINVAL;
4696 }
4697
4698 if (enable || disable) {
4699 status = video_outputsw_get();
4700 if (status < 0)
4701 return status;
4702 res = video_outputsw_set((status & ~disable) | enable);
4703 if (res)
4704 return res;
4705 }
4706
4707 return 0;
4708}
4709
4710static struct ibm_struct video_driver_data = {
4711 .name = "video",
4712 .read = video_read,
4713 .write = video_write,
4714 .exit = video_exit,
4715};
4716
4717#endif
4718
4719
4720
4721
4722
4723TPACPI_HANDLE(lght, root, "\\LGHT");
4724TPACPI_HANDLE(ledb, ec, "LEDB");
4725
4726static int light_get_status(void)
4727{
4728 int status = 0;
4729
4730 if (tp_features.light_status) {
4731 if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
4732 return -EIO;
4733 return (!!status);
4734 }
4735
4736 return -ENXIO;
4737}
4738
4739static int light_set_status(int status)
4740{
4741 int rc;
4742
4743 if (tp_features.light) {
4744 if (cmos_handle) {
4745 rc = acpi_evalf(cmos_handle, NULL, NULL, "vd",
4746 (status)?
4747 TP_CMOS_THINKLIGHT_ON :
4748 TP_CMOS_THINKLIGHT_OFF);
4749 } else {
4750 rc = acpi_evalf(lght_handle, NULL, NULL, "vd",
4751 (status)? 1 : 0);
4752 }
4753 return (rc)? 0 : -EIO;
4754 }
4755
4756 return -ENXIO;
4757}
4758
4759static void light_set_status_worker(struct work_struct *work)
4760{
4761 struct tpacpi_led_classdev *data =
4762 container_of(work, struct tpacpi_led_classdev, work);
4763
4764 if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
4765 light_set_status((data->new_state != TPACPI_LED_OFF));
4766}
4767
4768static void light_sysfs_set(struct led_classdev *led_cdev,
4769 enum led_brightness brightness)
4770{
4771 struct tpacpi_led_classdev *data =
4772 container_of(led_cdev,
4773 struct tpacpi_led_classdev,
4774 led_classdev);
4775 data->new_state = (brightness != LED_OFF) ?
4776 TPACPI_LED_ON : TPACPI_LED_OFF;
4777 queue_work(tpacpi_wq, &data->work);
4778}
4779
4780static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
4781{
4782 return (light_get_status() == 1)? LED_FULL : LED_OFF;
4783}
4784
4785static struct tpacpi_led_classdev tpacpi_led_thinklight = {
4786 .led_classdev = {
4787 .name = "tpacpi::thinklight",
4788 .brightness_set = &light_sysfs_set,
4789 .brightness_get = &light_sysfs_get,
4790 }
4791};
4792
4793static int __init light_init(struct ibm_init_struct *iibm)
4794{
4795 int rc;
4796
4797 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
4798
4799 TPACPI_ACPIHANDLE_INIT(ledb);
4800 TPACPI_ACPIHANDLE_INIT(lght);
4801 TPACPI_ACPIHANDLE_INIT(cmos);
4802 INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker);
4803
4804
4805 tp_features.light = (cmos_handle || lght_handle) && !ledb_handle;
4806
4807 if (tp_features.light)
4808
4809
4810 tp_features.light_status =
4811 acpi_evalf(ec_handle, NULL, "KBLT", "qv");
4812
4813 vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n",
4814 str_supported(tp_features.light),
4815 str_supported(tp_features.light_status));
4816
4817 if (!tp_features.light)
4818 return 1;
4819
4820 rc = led_classdev_register(&tpacpi_pdev->dev,
4821 &tpacpi_led_thinklight.led_classdev);
4822
4823 if (rc < 0) {
4824 tp_features.light = 0;
4825 tp_features.light_status = 0;
4826 } else {
4827 rc = 0;
4828 }
4829
4830 return rc;
4831}
4832
4833static void light_exit(void)
4834{
4835 led_classdev_unregister(&tpacpi_led_thinklight.led_classdev);
4836 if (work_pending(&tpacpi_led_thinklight.work))
4837 flush_workqueue(tpacpi_wq);
4838}
4839
4840static int light_read(char *p)
4841{
4842 int len = 0;
4843 int status;
4844
4845 if (!tp_features.light) {
4846 len += sprintf(p + len, "status:\t\tnot supported\n");
4847 } else if (!tp_features.light_status) {
4848 len += sprintf(p + len, "status:\t\tunknown\n");
4849 len += sprintf(p + len, "commands:\ton, off\n");
4850 } else {
4851 status = light_get_status();
4852 if (status < 0)
4853 return status;
4854 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
4855 len += sprintf(p + len, "commands:\ton, off\n");
4856 }
4857
4858 return len;
4859}
4860
4861static int light_write(char *buf)
4862{
4863 char *cmd;
4864 int newstatus = 0;
4865
4866 if (!tp_features.light)
4867 return -ENODEV;
4868
4869 while ((cmd = next_cmd(&buf))) {
4870 if (strlencmp(cmd, "on") == 0) {
4871 newstatus = 1;
4872 } else if (strlencmp(cmd, "off") == 0) {
4873 newstatus = 0;
4874 } else
4875 return -EINVAL;
4876 }
4877
4878 return light_set_status(newstatus);
4879}
4880
4881static struct ibm_struct light_driver_data = {
4882 .name = "light",
4883 .read = light_read,
4884 .write = light_write,
4885 .exit = light_exit,
4886};
4887
4888
4889
4890
4891
4892
4893static ssize_t cmos_command_store(struct device *dev,
4894 struct device_attribute *attr,
4895 const char *buf, size_t count)
4896{
4897 unsigned long cmos_cmd;
4898 int res;
4899
4900 if (parse_strtoul(buf, 21, &cmos_cmd))
4901 return -EINVAL;
4902
4903 res = issue_thinkpad_cmos_command(cmos_cmd);
4904 return (res)? res : count;
4905}
4906
4907static struct device_attribute dev_attr_cmos_command =
4908 __ATTR(cmos_command, S_IWUSR, NULL, cmos_command_store);
4909
4910
4911
4912static int __init cmos_init(struct ibm_init_struct *iibm)
4913{
4914 int res;
4915
4916 vdbg_printk(TPACPI_DBG_INIT,
4917 "initializing cmos commands subdriver\n");
4918
4919 TPACPI_ACPIHANDLE_INIT(cmos);
4920
4921 vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n",
4922 str_supported(cmos_handle != NULL));
4923
4924 res = device_create_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
4925 if (res)
4926 return res;
4927
4928 return (cmos_handle)? 0 : 1;
4929}
4930
4931static void cmos_exit(void)
4932{
4933 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
4934}
4935
4936static int cmos_read(char *p)
4937{
4938 int len = 0;
4939
4940
4941
4942 if (!cmos_handle)
4943 len += sprintf(p + len, "status:\t\tnot supported\n");
4944 else {
4945 len += sprintf(p + len, "status:\t\tsupported\n");
4946 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
4947 }
4948
4949 return len;
4950}
4951
4952static int cmos_write(char *buf)
4953{
4954 char *cmd;
4955 int cmos_cmd, res;
4956
4957 while ((cmd = next_cmd(&buf))) {
4958 if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
4959 cmos_cmd >= 0 && cmos_cmd <= 21) {
4960
4961 } else
4962 return -EINVAL;
4963
4964 res = issue_thinkpad_cmos_command(cmos_cmd);
4965 if (res)
4966 return res;
4967 }
4968
4969 return 0;
4970}
4971
4972static struct ibm_struct cmos_driver_data = {
4973 .name = "cmos",
4974 .read = cmos_read,
4975 .write = cmos_write,
4976 .exit = cmos_exit,
4977};
4978
4979
4980
4981
4982
4983enum led_access_mode {
4984 TPACPI_LED_NONE = 0,
4985 TPACPI_LED_570,
4986 TPACPI_LED_OLD,
4987 TPACPI_LED_NEW,
4988};
4989
4990enum {
4991 TPACPI_LED_EC_HLCL = 0x0c,
4992 TPACPI_LED_EC_HLBL = 0x0d,
4993 TPACPI_LED_EC_HLMS = 0x0e,
4994};
4995
4996static enum led_access_mode led_supported;
4997
4998TPACPI_HANDLE(led, ec, "SLED",
4999 "SYSL",
5000
5001 "LED",
5002 );
5003
5004#define TPACPI_LED_NUMLEDS 16
5005static struct tpacpi_led_classdev *tpacpi_leds;
5006static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS];
5007static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
5008
5009 "tpacpi::power",
5010 "tpacpi:orange:batt",
5011 "tpacpi:green:batt",
5012 "tpacpi::dock_active",
5013 "tpacpi::bay_active",
5014 "tpacpi::dock_batt",
5015 "tpacpi::unknown_led",
5016 "tpacpi::standby",
5017 "tpacpi::dock_status1",
5018 "tpacpi::dock_status2",
5019 "tpacpi::unknown_led2",
5020 "tpacpi::unknown_led3",
5021 "tpacpi::thinkvantage",
5022};
5023#define TPACPI_SAFE_LEDS 0x1081U
5024
5025static inline bool tpacpi_is_led_restricted(const unsigned int led)
5026{
5027#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
5028 return false;
5029#else
5030 return (1U & (TPACPI_SAFE_LEDS >> led)) == 0;
5031#endif
5032}
5033
5034static int led_get_status(const unsigned int led)
5035{
5036 int status;
5037 enum led_status_t led_s;
5038
5039 switch (led_supported) {
5040 case TPACPI_LED_570:
5041 if (!acpi_evalf(ec_handle,
5042 &status, "GLED", "dd", 1 << led))
5043 return -EIO;
5044 led_s = (status == 0)?
5045 TPACPI_LED_OFF :
5046 ((status == 1)?
5047 TPACPI_LED_ON :
5048 TPACPI_LED_BLINK);
5049 tpacpi_led_state_cache[led] = led_s;
5050 return led_s;
5051 default:
5052 return -ENXIO;
5053 }
5054
5055
5056}
5057
5058static int led_set_status(const unsigned int led,
5059 const enum led_status_t ledstatus)
5060{
5061
5062 static const unsigned int led_sled_arg1[] = { 0, 1, 3 };
5063 static const unsigned int led_led_arg1[] = { 0, 0x80, 0xc0 };
5064
5065 int rc = 0;
5066
5067 switch (led_supported) {
5068 case TPACPI_LED_570:
5069
5070 if (unlikely(led > 7))
5071 return -EINVAL;
5072 if (unlikely(tpacpi_is_led_restricted(led)))
5073 return -EPERM;
5074 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
5075 (1 << led), led_sled_arg1[ledstatus]))
5076 rc = -EIO;
5077 break;
5078 case TPACPI_LED_OLD:
5079
5080 if (unlikely(led > 7))
5081 return -EINVAL;
5082 if (unlikely(tpacpi_is_led_restricted(led)))
5083 return -EPERM;
5084 rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led));
5085 if (rc >= 0)
5086 rc = ec_write(TPACPI_LED_EC_HLBL,
5087 (ledstatus == TPACPI_LED_BLINK) << led);
5088 if (rc >= 0)
5089 rc = ec_write(TPACPI_LED_EC_HLCL,
5090 (ledstatus != TPACPI_LED_OFF) << led);
5091 break;
5092 case TPACPI_LED_NEW:
5093
5094 if (unlikely(led >= TPACPI_LED_NUMLEDS))
5095 return -EINVAL;
5096 if (unlikely(tpacpi_is_led_restricted(led)))
5097 return -EPERM;
5098 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
5099 led, led_led_arg1[ledstatus]))
5100 rc = -EIO;
5101 break;
5102 default:
5103 rc = -ENXIO;
5104 }
5105
5106 if (!rc)
5107 tpacpi_led_state_cache[led] = ledstatus;
5108
5109 return rc;
5110}
5111
5112static void led_set_status_worker(struct work_struct *work)
5113{
5114 struct tpacpi_led_classdev *data =
5115 container_of(work, struct tpacpi_led_classdev, work);
5116
5117 if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
5118 led_set_status(data->led, data->new_state);
5119}
5120
5121static void led_sysfs_set(struct led_classdev *led_cdev,
5122 enum led_brightness brightness)
5123{
5124 struct tpacpi_led_classdev *data = container_of(led_cdev,
5125 struct tpacpi_led_classdev, led_classdev);
5126
5127 if (brightness == LED_OFF)
5128 data->new_state = TPACPI_LED_OFF;
5129 else if (tpacpi_led_state_cache[data->led] != TPACPI_LED_BLINK)
5130 data->new_state = TPACPI_LED_ON;
5131 else
5132 data->new_state = TPACPI_LED_BLINK;
5133
5134 queue_work(tpacpi_wq, &data->work);
5135}
5136
5137static int led_sysfs_blink_set(struct led_classdev *led_cdev,
5138 unsigned long *delay_on, unsigned long *delay_off)
5139{
5140 struct tpacpi_led_classdev *data = container_of(led_cdev,
5141 struct tpacpi_led_classdev, led_classdev);
5142
5143
5144 if (*delay_on == 0 && *delay_off == 0) {
5145
5146 *delay_on = 500;
5147 *delay_off = 500;
5148 } else if ((*delay_on != 500) || (*delay_off != 500))
5149 return -EINVAL;
5150
5151 data->new_state = TPACPI_LED_BLINK;
5152 queue_work(tpacpi_wq, &data->work);
5153
5154 return 0;
5155}
5156
5157static enum led_brightness led_sysfs_get(struct led_classdev *led_cdev)
5158{
5159 int rc;
5160
5161 struct tpacpi_led_classdev *data = container_of(led_cdev,
5162 struct tpacpi_led_classdev, led_classdev);
5163
5164 rc = led_get_status(data->led);
5165
5166 if (rc == TPACPI_LED_OFF || rc < 0)
5167 rc = LED_OFF;
5168 else
5169 rc = LED_FULL;
5170
5171 return rc;
5172}
5173
5174static void led_exit(void)
5175{
5176 unsigned int i;
5177
5178 for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
5179 if (tpacpi_leds[i].led_classdev.name)
5180 led_classdev_unregister(&tpacpi_leds[i].led_classdev);
5181 }
5182
5183 kfree(tpacpi_leds);
5184}
5185
5186static int __init tpacpi_init_led(unsigned int led)
5187{
5188 int rc;
5189
5190 tpacpi_leds[led].led = led;
5191
5192
5193 if (!tpacpi_led_names[led])
5194 return 0;
5195
5196 tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set;
5197 tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set;
5198 if (led_supported == TPACPI_LED_570)
5199 tpacpi_leds[led].led_classdev.brightness_get =
5200 &led_sysfs_get;
5201
5202 tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led];
5203
5204 INIT_WORK(&tpacpi_leds[led].work, led_set_status_worker);
5205
5206 rc = led_classdev_register(&tpacpi_pdev->dev,
5207 &tpacpi_leds[led].led_classdev);
5208 if (rc < 0)
5209 tpacpi_leds[led].led_classdev.name = NULL;
5210
5211 return rc;
5212}
5213
5214static const struct tpacpi_quirk led_useful_qtable[] __initconst = {
5215 TPACPI_Q_IBM('1', 'E', 0x009f),
5216 TPACPI_Q_IBM('1', 'N', 0x009f),
5217 TPACPI_Q_IBM('1', 'G', 0x009f),
5218
5219 TPACPI_Q_IBM('1', 'I', 0x0097),
5220 TPACPI_Q_IBM('1', 'R', 0x0097),
5221 TPACPI_Q_IBM('7', '0', 0x0097),
5222 TPACPI_Q_IBM('1', 'Y', 0x0097),
5223 TPACPI_Q_IBM('1', 'W', 0x0097),
5224 TPACPI_Q_IBM('1', 'V', 0x0097),
5225 TPACPI_Q_IBM('7', '8', 0x0097),
5226 TPACPI_Q_IBM('7', '6', 0x0097),
5227
5228 TPACPI_Q_IBM('1', 'K', 0x00bf),
5229 TPACPI_Q_IBM('1', 'Q', 0x00bf),
5230 TPACPI_Q_IBM('1', 'U', 0x00bf),
5231 TPACPI_Q_IBM('7', '4', 0x00bf),
5232 TPACPI_Q_IBM('7', '5', 0x00bf),
5233
5234 TPACPI_Q_IBM('7', '9', 0x1f97),
5235 TPACPI_Q_IBM('7', '7', 0x1f97),
5236 TPACPI_Q_IBM('7', 'F', 0x1f97),
5237 TPACPI_Q_IBM('7', 'B', 0x1fb7),
5238
5239
5240
5241
5242 {
5243 .vendor = PCI_VENDOR_ID_LENOVO,
5244 .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
5245 .quirks = 0x1fffU,
5246 },
5247 {
5248 .vendor = PCI_VENDOR_ID_IBM,
5249 .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_UNKNOWN,
5250 .quirks = 0x00ffU,
5251 },
5252 {
5253 .vendor = PCI_VENDOR_ID_IBM,
5254 .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
5255 .quirks = 0x00bfU,
5256 },
5257};
5258
5259#undef TPACPI_LEDQ_IBM
5260#undef TPACPI_LEDQ_LNV
5261
5262static int __init led_init(struct ibm_init_struct *iibm)
5263{
5264 unsigned int i;
5265 int rc;
5266 unsigned long useful_leds;
5267
5268 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
5269
5270 TPACPI_ACPIHANDLE_INIT(led);
5271
5272 if (!led_handle)
5273
5274 led_supported = TPACPI_LED_NONE;
5275 else if (strlencmp(led_path, "SLED") == 0)
5276
5277 led_supported = TPACPI_LED_570;
5278 else if (strlencmp(led_path, "SYSL") == 0)
5279
5280 led_supported = TPACPI_LED_OLD;
5281 else
5282
5283 led_supported = TPACPI_LED_NEW;
5284
5285 vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n",
5286 str_supported(led_supported), led_supported);
5287
5288 if (led_supported == TPACPI_LED_NONE)
5289 return 1;
5290
5291 tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS,
5292 GFP_KERNEL);
5293 if (!tpacpi_leds) {
5294 printk(TPACPI_ERR "Out of memory for LED data\n");
5295 return -ENOMEM;
5296 }
5297
5298 useful_leds = tpacpi_check_quirks(led_useful_qtable,
5299 ARRAY_SIZE(led_useful_qtable));
5300
5301 for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
5302 if (!tpacpi_is_led_restricted(i) &&
5303 test_bit(i, &useful_leds)) {
5304 rc = tpacpi_init_led(i);
5305 if (rc < 0) {
5306 led_exit();
5307 return rc;
5308 }
5309 }
5310 }
5311
5312#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
5313 printk(TPACPI_NOTICE
5314 "warning: userspace override of important "
5315 "firmware LEDs is enabled\n");
5316#endif
5317 return 0;
5318}
5319
5320#define str_led_status(s) \
5321 ((s) == TPACPI_LED_OFF ? "off" : \
5322 ((s) == TPACPI_LED_ON ? "on" : "blinking"))
5323
5324static int led_read(char *p)
5325{
5326 int len = 0;
5327
5328 if (!led_supported) {
5329 len += sprintf(p + len, "status:\t\tnot supported\n");
5330 return len;
5331 }
5332 len += sprintf(p + len, "status:\t\tsupported\n");
5333
5334 if (led_supported == TPACPI_LED_570) {
5335
5336 int i, status;
5337 for (i = 0; i < 8; i++) {
5338 status = led_get_status(i);
5339 if (status < 0)
5340 return -EIO;
5341 len += sprintf(p + len, "%d:\t\t%s\n",
5342 i, str_led_status(status));
5343 }
5344 }
5345
5346 len += sprintf(p + len, "commands:\t"
5347 "<led> on, <led> off, <led> blink (<led> is 0-15)\n");
5348
5349 return len;
5350}
5351
5352static int led_write(char *buf)
5353{
5354 char *cmd;
5355 int led, rc;
5356 enum led_status_t s;
5357
5358 if (!led_supported)
5359 return -ENODEV;
5360
5361 while ((cmd = next_cmd(&buf))) {
5362 if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 15)
5363 return -EINVAL;
5364
5365 if (strstr(cmd, "off")) {
5366 s = TPACPI_LED_OFF;
5367 } else if (strstr(cmd, "on")) {
5368 s = TPACPI_LED_ON;
5369 } else if (strstr(cmd, "blink")) {
5370 s = TPACPI_LED_BLINK;
5371 } else {
5372 return -EINVAL;
5373 }
5374
5375 rc = led_set_status(led, s);
5376 if (rc < 0)
5377 return rc;
5378 }
5379
5380 return 0;
5381}
5382
5383static struct ibm_struct led_driver_data = {
5384 .name = "led",
5385 .read = led_read,
5386 .write = led_write,
5387 .exit = led_exit,
5388};
5389
5390
5391
5392
5393
5394TPACPI_HANDLE(beep, ec, "BEEP");
5395
5396#define TPACPI_BEEP_Q1 0x0001
5397
5398static const struct tpacpi_quirk beep_quirk_table[] __initconst = {
5399 TPACPI_Q_IBM('I', 'M', TPACPI_BEEP_Q1),
5400 TPACPI_Q_IBM('I', 'U', TPACPI_BEEP_Q1),
5401};
5402
5403static int __init beep_init(struct ibm_init_struct *iibm)
5404{
5405 unsigned long quirks;
5406
5407 vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n");
5408
5409 TPACPI_ACPIHANDLE_INIT(beep);
5410
5411 vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n",
5412 str_supported(beep_handle != NULL));
5413
5414 quirks = tpacpi_check_quirks(beep_quirk_table,
5415 ARRAY_SIZE(beep_quirk_table));
5416
5417 tp_features.beep_needs_two_args = !!(quirks & TPACPI_BEEP_Q1);
5418
5419 return (beep_handle)? 0 : 1;
5420}
5421
5422static int beep_read(char *p)
5423{
5424 int len = 0;
5425
5426 if (!beep_handle)
5427 len += sprintf(p + len, "status:\t\tnot supported\n");
5428 else {
5429 len += sprintf(p + len, "status:\t\tsupported\n");
5430 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
5431 }
5432
5433 return len;
5434}
5435
5436static int beep_write(char *buf)
5437{
5438 char *cmd;
5439 int beep_cmd;
5440
5441 if (!beep_handle)
5442 return -ENODEV;
5443
5444 while ((cmd = next_cmd(&buf))) {
5445 if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
5446 beep_cmd >= 0 && beep_cmd <= 17) {
5447
5448 } else
5449 return -EINVAL;
5450 if (tp_features.beep_needs_two_args) {
5451 if (!acpi_evalf(beep_handle, NULL, NULL, "vdd",
5452 beep_cmd, 0))
5453 return -EIO;
5454 } else {
5455 if (!acpi_evalf(beep_handle, NULL, NULL, "vd",
5456 beep_cmd))
5457 return -EIO;
5458 }
5459 }
5460
5461 return 0;
5462}
5463
5464static struct ibm_struct beep_driver_data = {
5465 .name = "beep",
5466 .read = beep_read,
5467 .write = beep_write,
5468};
5469
5470
5471
5472
5473
5474enum thermal_access_mode {
5475 TPACPI_THERMAL_NONE = 0,
5476 TPACPI_THERMAL_ACPI_TMP07,
5477 TPACPI_THERMAL_ACPI_UPDT,
5478 TPACPI_THERMAL_TPEC_8,
5479 TPACPI_THERMAL_TPEC_16,
5480};
5481
5482enum {
5483 TP_EC_THERMAL_TMP0 = 0x78,
5484 TP_EC_THERMAL_TMP8 = 0xC0,
5485 TP_EC_THERMAL_TMP_NA = -128,
5486};
5487
5488#define TPACPI_MAX_THERMAL_SENSORS 16
5489struct ibm_thermal_sensors_struct {
5490 s32 temp[TPACPI_MAX_THERMAL_SENSORS];
5491};
5492
5493static enum thermal_access_mode thermal_read_mode;
5494
5495
5496static int thermal_get_sensor(int idx, s32 *value)
5497{
5498 int t;
5499 s8 tmp;
5500 char tmpi[5];
5501
5502 t = TP_EC_THERMAL_TMP0;
5503
5504 switch (thermal_read_mode) {
5505#if TPACPI_MAX_THERMAL_SENSORS >= 16
5506 case TPACPI_THERMAL_TPEC_16:
5507 if (idx >= 8 && idx <= 15) {
5508 t = TP_EC_THERMAL_TMP8;
5509 idx -= 8;
5510 }
5511
5512#endif
5513 case TPACPI_THERMAL_TPEC_8:
5514 if (idx <= 7) {
5515 if (!acpi_ec_read(t + idx, &tmp))
5516 return -EIO;
5517 *value = tmp * 1000;
5518 return 0;
5519 }
5520 break;
5521
5522 case TPACPI_THERMAL_ACPI_UPDT:
5523 if (idx <= 7) {
5524 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
5525 if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
5526 return -EIO;
5527 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
5528 return -EIO;
5529 *value = (t - 2732) * 100;
5530 return 0;
5531 }
5532 break;
5533
5534 case TPACPI_THERMAL_ACPI_TMP07:
5535 if (idx <= 7) {
5536 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
5537 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
5538 return -EIO;
5539 if (t > 127 || t < -127)
5540 t = TP_EC_THERMAL_TMP_NA;
5541 *value = t * 1000;
5542 return 0;
5543 }
5544 break;
5545
5546 case TPACPI_THERMAL_NONE:
5547 default:
5548 return -ENOSYS;
5549 }
5550
5551 return -EINVAL;
5552}
5553
5554static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
5555{
5556 int res, i;
5557 int n;
5558
5559 n = 8;
5560 i = 0;
5561
5562 if (!s)
5563 return -EINVAL;
5564
5565 if (thermal_read_mode == TPACPI_THERMAL_TPEC_16)
5566 n = 16;
5567
5568 for (i = 0 ; i < n; i++) {
5569 res = thermal_get_sensor(i, &s->temp[i]);
5570 if (res)
5571 return res;
5572 }
5573
5574 return n;
5575}
5576
5577
5578
5579static ssize_t thermal_temp_input_show(struct device *dev,
5580 struct device_attribute *attr,
5581 char *buf)
5582{
5583 struct sensor_device_attribute *sensor_attr =
5584 to_sensor_dev_attr(attr);
5585 int idx = sensor_attr->index;
5586 s32 value;
5587 int res;
5588
5589 res = thermal_get_sensor(idx, &value);
5590 if (res)
5591 return res;
5592 if (value == TP_EC_THERMAL_TMP_NA * 1000)
5593 return -ENXIO;
5594
5595 return snprintf(buf, PAGE_SIZE, "%d\n", value);
5596}
5597
5598#define THERMAL_SENSOR_ATTR_TEMP(_idxA, _idxB) \
5599 SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, \
5600 thermal_temp_input_show, NULL, _idxB)
5601
5602static struct sensor_device_attribute sensor_dev_attr_thermal_temp_input[] = {
5603 THERMAL_SENSOR_ATTR_TEMP(1, 0),
5604 THERMAL_SENSOR_ATTR_TEMP(2, 1),
5605 THERMAL_SENSOR_ATTR_TEMP(3, 2),
5606 THERMAL_SENSOR_ATTR_TEMP(4, 3),
5607 THERMAL_SENSOR_ATTR_TEMP(5, 4),
5608 THERMAL_SENSOR_ATTR_TEMP(6, 5),
5609 THERMAL_SENSOR_ATTR_TEMP(7, 6),
5610 THERMAL_SENSOR_ATTR_TEMP(8, 7),
5611 THERMAL_SENSOR_ATTR_TEMP(9, 8),
5612 THERMAL_SENSOR_ATTR_TEMP(10, 9),
5613 THERMAL_SENSOR_ATTR_TEMP(11, 10),
5614 THERMAL_SENSOR_ATTR_TEMP(12, 11),
5615 THERMAL_SENSOR_ATTR_TEMP(13, 12),
5616 THERMAL_SENSOR_ATTR_TEMP(14, 13),
5617 THERMAL_SENSOR_ATTR_TEMP(15, 14),
5618 THERMAL_SENSOR_ATTR_TEMP(16, 15),
5619};
5620
5621#define THERMAL_ATTRS(X) \
5622 &sensor_dev_attr_thermal_temp_input[X].dev_attr.attr
5623
5624static struct attribute *thermal_temp_input_attr[] = {
5625 THERMAL_ATTRS(8),
5626 THERMAL_ATTRS(9),
5627 THERMAL_ATTRS(10),
5628 THERMAL_ATTRS(11),
5629 THERMAL_ATTRS(12),
5630 THERMAL_ATTRS(13),
5631 THERMAL_ATTRS(14),
5632 THERMAL_ATTRS(15),
5633 THERMAL_ATTRS(0),
5634 THERMAL_ATTRS(1),
5635 THERMAL_ATTRS(2),
5636 THERMAL_ATTRS(3),
5637 THERMAL_ATTRS(4),
5638 THERMAL_ATTRS(5),
5639 THERMAL_ATTRS(6),
5640 THERMAL_ATTRS(7),
5641 NULL
5642};
5643
5644static const struct attribute_group thermal_temp_input16_group = {
5645 .attrs = thermal_temp_input_attr
5646};
5647
5648static const struct attribute_group thermal_temp_input8_group = {
5649 .attrs = &thermal_temp_input_attr[8]
5650};
5651
5652#undef THERMAL_SENSOR_ATTR_TEMP
5653#undef THERMAL_ATTRS
5654
5655
5656
5657static int __init thermal_init(struct ibm_init_struct *iibm)
5658{
5659 u8 t, ta1, ta2;
5660 int i;
5661 int acpi_tmp7;
5662 int res;
5663
5664 vdbg_printk(TPACPI_DBG_INIT, "initializing thermal subdriver\n");
5665
5666 acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
5667
5668 if (thinkpad_id.ec_model) {
5669
5670
5671
5672
5673
5674
5675
5676 ta1 = ta2 = 0;
5677 for (i = 0; i < 8; i++) {
5678 if (acpi_ec_read(TP_EC_THERMAL_TMP0 + i, &t)) {
5679 ta1 |= t;
5680 } else {
5681 ta1 = 0;
5682 break;
5683 }
5684 if (acpi_ec_read(TP_EC_THERMAL_TMP8 + i, &t)) {
5685 ta2 |= t;
5686 } else {
5687 ta1 = 0;
5688 break;
5689 }
5690 }
5691 if (ta1 == 0) {
5692
5693 if (acpi_tmp7) {
5694 printk(TPACPI_ERR
5695 "ThinkPad ACPI EC access misbehaving, "
5696 "falling back to ACPI TMPx access "
5697 "mode\n");
5698 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
5699 } else {
5700 printk(TPACPI_ERR
5701 "ThinkPad ACPI EC access misbehaving, "
5702 "disabling thermal sensors access\n");
5703 thermal_read_mode = TPACPI_THERMAL_NONE;
5704 }
5705 } else {
5706 thermal_read_mode =
5707 (ta2 != 0) ?
5708 TPACPI_THERMAL_TPEC_16 : TPACPI_THERMAL_TPEC_8;
5709 }
5710 } else if (acpi_tmp7) {
5711 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
5712
5713 thermal_read_mode = TPACPI_THERMAL_ACPI_UPDT;
5714 } else {
5715
5716 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
5717 }
5718 } else {
5719
5720 thermal_read_mode = TPACPI_THERMAL_NONE;
5721 }
5722
5723 vdbg_printk(TPACPI_DBG_INIT, "thermal is %s, mode %d\n",
5724 str_supported(thermal_read_mode != TPACPI_THERMAL_NONE),
5725 thermal_read_mode);
5726
5727 switch (thermal_read_mode) {
5728 case TPACPI_THERMAL_TPEC_16:
5729 res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
5730 &thermal_temp_input16_group);
5731 if (res)
5732 return res;
5733 break;
5734 case TPACPI_THERMAL_TPEC_8:
5735 case TPACPI_THERMAL_ACPI_TMP07:
5736 case TPACPI_THERMAL_ACPI_UPDT:
5737 res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
5738 &thermal_temp_input8_group);
5739 if (res)
5740 return res;
5741 break;
5742 case TPACPI_THERMAL_NONE:
5743 default:
5744 return 1;
5745 }
5746
5747 return 0;
5748}
5749
5750static void thermal_exit(void)
5751{
5752 switch (thermal_read_mode) {
5753 case TPACPI_THERMAL_TPEC_16:
5754 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
5755 &thermal_temp_input16_group);
5756 break;
5757 case TPACPI_THERMAL_TPEC_8:
5758 case TPACPI_THERMAL_ACPI_TMP07:
5759 case TPACPI_THERMAL_ACPI_UPDT:
5760 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
5761 &thermal_temp_input16_group);
5762 break;
5763 case TPACPI_THERMAL_NONE:
5764 default:
5765 break;
5766 }
5767}
5768
5769static int thermal_read(char *p)
5770{
5771 int len = 0;
5772 int n, i;
5773 struct ibm_thermal_sensors_struct t;
5774
5775 n = thermal_get_sensors(&t);
5776 if (unlikely(n < 0))
5777 return n;
5778
5779 len += sprintf(p + len, "temperatures:\t");
5780
5781 if (n > 0) {
5782 for (i = 0; i < (n - 1); i++)
5783 len += sprintf(p + len, "%d ", t.temp[i] / 1000);
5784 len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
5785 } else
5786 len += sprintf(p + len, "not supported\n");
5787
5788 return len;
5789}
5790
5791static struct ibm_struct thermal_driver_data = {
5792 .name = "thermal",
5793 .read = thermal_read,
5794 .exit = thermal_exit,
5795};
5796
5797
5798
5799
5800
5801static u8 ecdump_regs[256];
5802
5803static int ecdump_read(char *p)
5804{
5805 int len = 0;
5806 int i, j;
5807 u8 v;
5808
5809 len += sprintf(p + len, "EC "
5810 " +00 +01 +02 +03 +04 +05 +06 +07"
5811 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
5812 for (i = 0; i < 256; i += 16) {
5813 len += sprintf(p + len, "EC 0x%02x:", i);
5814 for (j = 0; j < 16; j++) {
5815 if (!acpi_ec_read(i + j, &v))
5816 break;
5817 if (v != ecdump_regs[i + j])
5818 len += sprintf(p + len, " *%02x", v);
5819 else
5820 len += sprintf(p + len, " %02x", v);
5821 ecdump_regs[i + j] = v;
5822 }
5823 len += sprintf(p + len, "\n");
5824 if (j != 16)
5825 break;
5826 }
5827
5828
5829#if 0
5830 len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
5831 " (<offset> is 00-ff, <value> is 00-ff)\n");
5832 len += sprintf(p + len, "commands:\t0x<offset> <value> "
5833 " (<offset> is 00-ff, <value> is 0-255)\n");
5834#endif
5835 return len;
5836}
5837
5838static int ecdump_write(char *buf)
5839{
5840 char *cmd;
5841 int i, v;
5842
5843 while ((cmd = next_cmd(&buf))) {
5844 if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
5845
5846 } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
5847
5848 } else
5849 return -EINVAL;
5850 if (i >= 0 && i < 256 && v >= 0 && v < 256) {
5851 if (!acpi_ec_write(i, v))
5852 return -EIO;
5853 } else
5854 return -EINVAL;
5855 }
5856
5857 return 0;
5858}
5859
5860static struct ibm_struct ecdump_driver_data = {
5861 .name = "ecdump",
5862 .read = ecdump_read,
5863 .write = ecdump_write,
5864 .flags.experimental = 1,
5865};
5866
5867
5868
5869
5870
5871#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891enum {
5892 TP_EC_BACKLIGHT = 0x31,
5893
5894
5895 TP_EC_BACKLIGHT_LVLMSK = 0x1F,
5896 TP_EC_BACKLIGHT_CMDMSK = 0xE0,
5897 TP_EC_BACKLIGHT_MAPSW = 0x20,
5898};
5899
5900enum tpacpi_brightness_access_mode {
5901 TPACPI_BRGHT_MODE_AUTO = 0,
5902 TPACPI_BRGHT_MODE_EC,
5903 TPACPI_BRGHT_MODE_UCMS_STEP,
5904 TPACPI_BRGHT_MODE_ECNVRAM,
5905 TPACPI_BRGHT_MODE_MAX
5906};
5907
5908static struct backlight_device *ibm_backlight_device;
5909
5910static enum tpacpi_brightness_access_mode brightness_mode =
5911 TPACPI_BRGHT_MODE_MAX;
5912
5913static unsigned int brightness_enable = 2;
5914
5915static struct mutex brightness_mutex;
5916
5917
5918
5919static unsigned int tpacpi_brightness_nvram_get(void)
5920{
5921 u8 lnvram;
5922
5923 lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
5924 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
5925 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
5926 lnvram &= (tp_features.bright_16levels) ? 0x0f : 0x07;
5927
5928 return lnvram;
5929}
5930
5931static void tpacpi_brightness_checkpoint_nvram(void)
5932{
5933 u8 lec = 0;
5934 u8 b_nvram;
5935
5936 if (brightness_mode != TPACPI_BRGHT_MODE_ECNVRAM)
5937 return;
5938
5939 vdbg_printk(TPACPI_DBG_BRGHT,
5940 "trying to checkpoint backlight level to NVRAM...\n");
5941
5942 if (mutex_lock_killable(&brightness_mutex) < 0)
5943 return;
5944
5945 if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
5946 goto unlock;
5947 lec &= TP_EC_BACKLIGHT_LVLMSK;
5948 b_nvram = nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS);
5949
5950 if (lec != ((b_nvram & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
5951 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS)) {
5952
5953 b_nvram &= ~(TP_NVRAM_MASK_LEVEL_BRIGHTNESS <<
5954 TP_NVRAM_POS_LEVEL_BRIGHTNESS);
5955 b_nvram |= lec;
5956 nvram_write_byte(b_nvram, TP_NVRAM_ADDR_BRIGHTNESS);
5957 dbg_printk(TPACPI_DBG_BRGHT,
5958 "updated NVRAM backlight level to %u (0x%02x)\n",
5959 (unsigned int) lec, (unsigned int) b_nvram);
5960 } else
5961 vdbg_printk(TPACPI_DBG_BRGHT,
5962 "NVRAM backlight level already is %u (0x%02x)\n",
5963 (unsigned int) lec, (unsigned int) b_nvram);
5964
5965unlock:
5966 mutex_unlock(&brightness_mutex);
5967}
5968
5969
5970
5971static int tpacpi_brightness_get_raw(int *status)
5972{
5973 u8 lec = 0;
5974
5975 switch (brightness_mode) {
5976 case TPACPI_BRGHT_MODE_UCMS_STEP:
5977 *status = tpacpi_brightness_nvram_get();
5978 return 0;
5979 case TPACPI_BRGHT_MODE_EC:
5980 case TPACPI_BRGHT_MODE_ECNVRAM:
5981 if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
5982 return -EIO;
5983 *status = lec;
5984 return 0;
5985 default:
5986 return -ENXIO;
5987 }
5988}
5989
5990
5991
5992static int tpacpi_brightness_set_ec(unsigned int value)
5993{
5994 u8 lec = 0;
5995
5996 if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
5997 return -EIO;
5998
5999 if (unlikely(!acpi_ec_write(TP_EC_BACKLIGHT,
6000 (lec & TP_EC_BACKLIGHT_CMDMSK) |
6001 (value & TP_EC_BACKLIGHT_LVLMSK))))
6002 return -EIO;
6003
6004 return 0;
6005}
6006
6007
6008static int tpacpi_brightness_set_ucmsstep(unsigned int value)
6009{
6010 int cmos_cmd, inc;
6011 unsigned int current_value, i;
6012
6013 current_value = tpacpi_brightness_nvram_get();
6014
6015 if (value == current_value)
6016 return 0;
6017
6018 cmos_cmd = (value > current_value) ?
6019 TP_CMOS_BRIGHTNESS_UP :
6020 TP_CMOS_BRIGHTNESS_DOWN;
6021 inc = (value > current_value) ? 1 : -1;
6022
6023 for (i = current_value; i != value; i += inc)
6024 if (issue_thinkpad_cmos_command(cmos_cmd))
6025 return -EIO;
6026
6027 return 0;
6028}
6029
6030
6031static int brightness_set(unsigned int value)
6032{
6033 int res;
6034
6035 if (value > ((tp_features.bright_16levels)? 15 : 7) ||
6036 value < 0)
6037 return -EINVAL;
6038
6039 vdbg_printk(TPACPI_DBG_BRGHT,
6040 "set backlight level to %d\n", value);
6041
6042 res = mutex_lock_killable(&brightness_mutex);
6043 if (res < 0)
6044 return res;
6045
6046 switch (brightness_mode) {
6047 case TPACPI_BRGHT_MODE_EC:
6048 case TPACPI_BRGHT_MODE_ECNVRAM:
6049 res = tpacpi_brightness_set_ec(value);
6050 break;
6051 case TPACPI_BRGHT_MODE_UCMS_STEP:
6052 res = tpacpi_brightness_set_ucmsstep(value);
6053 break;
6054 default:
6055 res = -ENXIO;
6056 }
6057
6058 mutex_unlock(&brightness_mutex);
6059 return res;
6060}
6061
6062
6063
6064static int brightness_update_status(struct backlight_device *bd)
6065{
6066 unsigned int level =
6067 (bd->props.fb_blank == FB_BLANK_UNBLANK &&
6068 bd->props.power == FB_BLANK_UNBLANK) ?
6069 bd->props.brightness : 0;
6070
6071 dbg_printk(TPACPI_DBG_BRGHT,
6072 "backlight: attempt to set level to %d\n",
6073 level);
6074
6075
6076
6077 return brightness_set(level);
6078}
6079
6080static int brightness_get(struct backlight_device *bd)
6081{
6082 int status, res;
6083
6084 res = mutex_lock_killable(&brightness_mutex);
6085 if (res < 0)
6086 return 0;
6087
6088 res = tpacpi_brightness_get_raw(&status);
6089
6090 mutex_unlock(&brightness_mutex);
6091
6092 if (res < 0)
6093 return 0;
6094
6095 return status & TP_EC_BACKLIGHT_LVLMSK;
6096}
6097
6098static struct backlight_ops ibm_backlight_data = {
6099 .get_brightness = brightness_get,
6100 .update_status = brightness_update_status,
6101};
6102
6103
6104
6105
6106
6107
6108
6109
6110#define TPACPI_BRGHT_Q_NOEC 0x0001
6111#define TPACPI_BRGHT_Q_EC 0x0002
6112#define TPACPI_BRGHT_Q_ASK 0x8000
6113
6114static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6115
6116 TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC),
6117
6118
6119 TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),
6120 TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6121 TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6122 TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6123
6124
6125 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
6126 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
6127 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
6128
6129
6130 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC),
6131 TPACPI_Q_IBM('7', '4', TPACPI_BRGHT_Q_NOEC),
6132 TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC),
6133};
6134
6135static int __init brightness_init(struct ibm_init_struct *iibm)
6136{
6137 int b;
6138 unsigned long quirks;
6139
6140 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n");
6141
6142 mutex_init(&brightness_mutex);
6143
6144 quirks = tpacpi_check_quirks(brightness_quirk_table,
6145 ARRAY_SIZE(brightness_quirk_table));
6146
6147
6148
6149
6150
6151
6152 b = tpacpi_check_std_acpi_brightness_support();
6153 if (b > 0) {
6154
6155 if (acpi_video_backlight_support()) {
6156 if (brightness_enable > 1) {
6157 printk(TPACPI_NOTICE
6158 "Standard ACPI backlight interface "
6159 "available, not loading native one.\n");
6160 return 1;
6161 } else if (brightness_enable == 1) {
6162 printk(TPACPI_NOTICE
6163 "Backlight control force enabled, even if standard "
6164 "ACPI backlight interface is available\n");
6165 }
6166 } else {
6167 if (brightness_enable > 1) {
6168 printk(TPACPI_NOTICE
6169 "Standard ACPI backlight interface not "
6170 "available, thinkpad_acpi native "
6171 "brightness control enabled\n");
6172 }
6173 }
6174 }
6175
6176 if (!brightness_enable) {
6177 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
6178 "brightness support disabled by "
6179 "module parameter\n");
6180 return 1;
6181 }
6182
6183 if (b > 16) {
6184 printk(TPACPI_ERR
6185 "Unsupported brightness interface, "
6186 "please contact %s\n", TPACPI_MAIL);
6187 return 1;
6188 }
6189 if (b == 16)
6190 tp_features.bright_16levels = 1;
6191
6192
6193
6194
6195
6196
6197 if (brightness_mode > TPACPI_BRGHT_MODE_MAX)
6198 return -EINVAL;
6199
6200
6201 if (brightness_mode == TPACPI_BRGHT_MODE_AUTO ||
6202 brightness_mode == TPACPI_BRGHT_MODE_MAX) {
6203 if (quirks & TPACPI_BRGHT_Q_EC)
6204 brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM;
6205 else
6206 brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
6207
6208 dbg_printk(TPACPI_DBG_BRGHT,
6209 "driver auto-selected brightness_mode=%d\n",
6210 brightness_mode);
6211 }
6212
6213
6214 if (thinkpad_id.vendor != PCI_VENDOR_ID_IBM &&
6215 (brightness_mode == TPACPI_BRGHT_MODE_ECNVRAM ||
6216 brightness_mode == TPACPI_BRGHT_MODE_EC))
6217 return -EINVAL;
6218
6219 if (tpacpi_brightness_get_raw(&b) < 0)
6220 return 1;
6221
6222 if (tp_features.bright_16levels)
6223 printk(TPACPI_INFO
6224 "detected a 16-level brightness capable ThinkPad\n");
6225
6226 ibm_backlight_device = backlight_device_register(
6227 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
6228 &ibm_backlight_data);
6229 if (IS_ERR(ibm_backlight_device)) {
6230 int rc = PTR_ERR(ibm_backlight_device);
6231 ibm_backlight_device = NULL;
6232 printk(TPACPI_ERR "Could not register backlight device\n");
6233 return rc;
6234 }
6235 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
6236 "brightness is supported\n");
6237
6238 if (quirks & TPACPI_BRGHT_Q_ASK) {
6239 printk(TPACPI_NOTICE
6240 "brightness: will use unverified default: "
6241 "brightness_mode=%d\n", brightness_mode);
6242 printk(TPACPI_NOTICE
6243 "brightness: please report to %s whether it works well "
6244 "or not on your ThinkPad\n", TPACPI_MAIL);
6245 }
6246
6247 ibm_backlight_device->props.max_brightness =
6248 (tp_features.bright_16levels)? 15 : 7;
6249 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6250 backlight_update_status(ibm_backlight_device);
6251
6252 return 0;
6253}
6254
6255static void brightness_suspend(pm_message_t state)
6256{
6257 tpacpi_brightness_checkpoint_nvram();
6258}
6259
6260static void brightness_shutdown(void)
6261{
6262 tpacpi_brightness_checkpoint_nvram();
6263}
6264
6265static void brightness_exit(void)
6266{
6267 if (ibm_backlight_device) {
6268 vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_BRGHT,
6269 "calling backlight_device_unregister()\n");
6270 backlight_device_unregister(ibm_backlight_device);
6271 }
6272
6273 tpacpi_brightness_checkpoint_nvram();
6274}
6275
6276static int brightness_read(char *p)
6277{
6278 int len = 0;
6279 int level;
6280
6281 level = brightness_get(NULL);
6282 if (level < 0) {
6283 len += sprintf(p + len, "level:\t\tunreadable\n");
6284 } else {
6285 len += sprintf(p + len, "level:\t\t%d\n", level);
6286 len += sprintf(p + len, "commands:\tup, down\n");
6287 len += sprintf(p + len, "commands:\tlevel <level>"
6288 " (<level> is 0-%d)\n",
6289 (tp_features.bright_16levels) ? 15 : 7);
6290 }
6291
6292 return len;
6293}
6294
6295static int brightness_write(char *buf)
6296{
6297 int level;
6298 int rc;
6299 char *cmd;
6300 int max_level = (tp_features.bright_16levels) ? 15 : 7;
6301
6302 level = brightness_get(NULL);
6303 if (level < 0)
6304 return level;
6305
6306 while ((cmd = next_cmd(&buf))) {
6307 if (strlencmp(cmd, "up") == 0) {
6308 if (level < max_level)
6309 level++;
6310 } else if (strlencmp(cmd, "down") == 0) {
6311 if (level > 0)
6312 level--;
6313 } else if (sscanf(cmd, "level %d", &level) == 1 &&
6314 level >= 0 && level <= max_level) {
6315
6316 } else
6317 return -EINVAL;
6318 }
6319
6320 tpacpi_disclose_usertask("procfs brightness",
6321 "set level to %d\n", level);
6322
6323
6324
6325
6326
6327 rc = brightness_set(level);
6328 return (rc == -EINTR)? -ERESTARTSYS : rc;
6329}
6330
6331static struct ibm_struct brightness_driver_data = {
6332 .name = "brightness",
6333 .read = brightness_read,
6334 .write = brightness_write,
6335 .exit = brightness_exit,
6336 .suspend = brightness_suspend,
6337 .shutdown = brightness_shutdown,
6338};
6339
6340
6341
6342
6343
6344static int volume_offset = 0x30;
6345
6346static int volume_read(char *p)
6347{
6348 int len = 0;
6349 u8 level;
6350
6351 if (!acpi_ec_read(volume_offset, &level)) {
6352 len += sprintf(p + len, "level:\t\tunreadable\n");
6353 } else {
6354 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
6355 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
6356 len += sprintf(p + len, "commands:\tup, down, mute\n");
6357 len += sprintf(p + len, "commands:\tlevel <level>"
6358 " (<level> is 0-15)\n");
6359 }
6360
6361 return len;
6362}
6363
6364static int volume_write(char *buf)
6365{
6366 int cmos_cmd, inc, i;
6367 u8 level, mute;
6368 int new_level, new_mute;
6369 char *cmd;
6370
6371 while ((cmd = next_cmd(&buf))) {
6372 if (!acpi_ec_read(volume_offset, &level))
6373 return -EIO;
6374 new_mute = mute = level & 0x40;
6375 new_level = level = level & 0xf;
6376
6377 if (strlencmp(cmd, "up") == 0) {
6378 if (mute)
6379 new_mute = 0;
6380 else
6381 new_level = level == 15 ? 15 : level + 1;
6382 } else if (strlencmp(cmd, "down") == 0) {
6383 if (mute)
6384 new_mute = 0;
6385 else
6386 new_level = level == 0 ? 0 : level - 1;
6387 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
6388 new_level >= 0 && new_level <= 15) {
6389
6390 } else if (strlencmp(cmd, "mute") == 0) {
6391 new_mute = 0x40;
6392 } else
6393 return -EINVAL;
6394
6395 if (new_level != level) {
6396
6397
6398 cmos_cmd = (new_level > level) ?
6399 TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN;
6400 inc = new_level > level ? 1 : -1;
6401
6402 if (mute && (issue_thinkpad_cmos_command(cmos_cmd) ||
6403 !acpi_ec_write(volume_offset, level)))
6404 return -EIO;
6405
6406 for (i = level; i != new_level; i += inc)
6407 if (issue_thinkpad_cmos_command(cmos_cmd) ||
6408 !acpi_ec_write(volume_offset, i + inc))
6409 return -EIO;
6410
6411 if (mute &&
6412 (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) ||
6413 !acpi_ec_write(volume_offset, new_level + mute))) {
6414 return -EIO;
6415 }
6416 }
6417
6418 if (new_mute != mute) {
6419
6420
6421 cmos_cmd = (new_mute) ?
6422 TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP;
6423
6424 if (issue_thinkpad_cmos_command(cmos_cmd) ||
6425 !acpi_ec_write(volume_offset, level + new_mute))
6426 return -EIO;
6427 }
6428 }
6429
6430 return 0;
6431}
6432
6433static struct ibm_struct volume_driver_data = {
6434 .name = "volume",
6435 .read = volume_read,
6436 .write = volume_write,
6437};
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559enum {
6560 fan_status_offset = 0x2f,
6561 fan_rpm_offset = 0x84,
6562
6563 fan_select_offset = 0x31,
6564
6565
6566 TP_EC_FAN_FULLSPEED = 0x40,
6567 TP_EC_FAN_AUTO = 0x80,
6568
6569 TPACPI_FAN_LAST_LEVEL = 0x100,
6570};
6571
6572enum fan_status_access_mode {
6573 TPACPI_FAN_NONE = 0,
6574 TPACPI_FAN_RD_ACPI_GFAN,
6575 TPACPI_FAN_RD_TPEC,
6576};
6577
6578enum fan_control_access_mode {
6579 TPACPI_FAN_WR_NONE = 0,
6580 TPACPI_FAN_WR_ACPI_SFAN,
6581 TPACPI_FAN_WR_TPEC,
6582 TPACPI_FAN_WR_ACPI_FANS,
6583};
6584
6585enum fan_control_commands {
6586 TPACPI_FAN_CMD_SPEED = 0x0001,
6587 TPACPI_FAN_CMD_LEVEL = 0x0002,
6588 TPACPI_FAN_CMD_ENABLE = 0x0004,
6589
6590};
6591
6592static int fan_control_allowed;
6593
6594static enum fan_status_access_mode fan_status_access_mode;
6595static enum fan_control_access_mode fan_control_access_mode;
6596static enum fan_control_commands fan_control_commands;
6597
6598static u8 fan_control_initial_status;
6599static u8 fan_control_desired_level;
6600static u8 fan_control_resume_level;
6601static int fan_watchdog_maxinterval;
6602
6603static struct mutex fan_mutex;
6604
6605static void fan_watchdog_fire(struct work_struct *ignored);
6606static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
6607
6608TPACPI_HANDLE(fans, ec, "FANS");
6609TPACPI_HANDLE(gfan, ec, "GFAN",
6610 "\\FSPD",
6611 );
6612TPACPI_HANDLE(sfan, ec, "SFAN",
6613 "JFNS",
6614 );
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632static void fan_quirk1_setup(void)
6633{
6634 if (fan_control_initial_status == 0x07) {
6635 printk(TPACPI_NOTICE
6636 "fan_init: initial fan status is unknown, "
6637 "assuming it is in auto mode\n");
6638 tp_features.fan_ctrl_status_undef = 1;
6639 }
6640}
6641
6642static void fan_quirk1_handle(u8 *fan_status)
6643{
6644 if (unlikely(tp_features.fan_ctrl_status_undef)) {
6645 if (*fan_status != fan_control_initial_status) {
6646
6647
6648
6649 tp_features.fan_ctrl_status_undef = 0;
6650 } else {
6651
6652
6653 *fan_status = TP_EC_FAN_AUTO;
6654 }
6655 }
6656}
6657
6658
6659static bool fan_select_fan1(void)
6660{
6661 if (tp_features.second_fan) {
6662 u8 val;
6663
6664 if (ec_read(fan_select_offset, &val) < 0)
6665 return false;
6666 val &= 0xFEU;
6667 if (ec_write(fan_select_offset, val) < 0)
6668 return false;
6669 }
6670 return true;
6671}
6672
6673
6674static bool fan_select_fan2(void)
6675{
6676 u8 val;
6677
6678 if (!tp_features.second_fan)
6679 return false;
6680
6681 if (ec_read(fan_select_offset, &val) < 0)
6682 return false;
6683 val |= 0x01U;
6684 if (ec_write(fan_select_offset, val) < 0)
6685 return false;
6686
6687 return true;
6688}
6689
6690
6691
6692
6693static void fan_update_desired_level(u8 status)
6694{
6695 if ((status &
6696 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
6697 if (status > 7)
6698 fan_control_desired_level = 7;
6699 else
6700 fan_control_desired_level = status;
6701 }
6702}
6703
6704static int fan_get_status(u8 *status)
6705{
6706 u8 s;
6707
6708
6709
6710
6711 switch (fan_status_access_mode) {
6712 case TPACPI_FAN_RD_ACPI_GFAN:
6713
6714
6715 if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
6716 return -EIO;
6717
6718 if (likely(status))
6719 *status = s & 0x07;
6720
6721 break;
6722
6723 case TPACPI_FAN_RD_TPEC:
6724
6725 if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
6726 return -EIO;
6727
6728 if (likely(status)) {
6729 *status = s;
6730 fan_quirk1_handle(status);
6731 }
6732
6733 break;
6734
6735 default:
6736 return -ENXIO;
6737 }
6738
6739 return 0;
6740}
6741
6742static int fan_get_status_safe(u8 *status)
6743{
6744 int rc;
6745 u8 s;
6746
6747 if (mutex_lock_killable(&fan_mutex))
6748 return -ERESTARTSYS;
6749 rc = fan_get_status(&s);
6750 if (!rc)
6751 fan_update_desired_level(s);
6752 mutex_unlock(&fan_mutex);
6753
6754 if (status)
6755 *status = s;
6756
6757 return rc;
6758}
6759
6760static int fan_get_speed(unsigned int *speed)
6761{
6762 u8 hi, lo;
6763
6764 switch (fan_status_access_mode) {
6765 case TPACPI_FAN_RD_TPEC:
6766
6767 if (unlikely(!fan_select_fan1()))
6768 return -EIO;
6769 if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
6770 !acpi_ec_read(fan_rpm_offset + 1, &hi)))
6771 return -EIO;
6772
6773 if (likely(speed))
6774 *speed = (hi << 8) | lo;
6775
6776 break;
6777
6778 default:
6779 return -ENXIO;
6780 }
6781
6782 return 0;
6783}
6784
6785static int fan2_get_speed(unsigned int *speed)
6786{
6787 u8 hi, lo;
6788 bool rc;
6789
6790 switch (fan_status_access_mode) {
6791 case TPACPI_FAN_RD_TPEC:
6792
6793 if (unlikely(!fan_select_fan2()))
6794 return -EIO;
6795 rc = !acpi_ec_read(fan_rpm_offset, &lo) ||
6796 !acpi_ec_read(fan_rpm_offset + 1, &hi);
6797 fan_select_fan1();
6798 if (rc)
6799 return -EIO;
6800
6801 if (likely(speed))
6802 *speed = (hi << 8) | lo;
6803
6804 break;
6805
6806 default:
6807 return -ENXIO;
6808 }
6809
6810 return 0;
6811}
6812
6813static int fan_set_level(int level)
6814{
6815 if (!fan_control_allowed)
6816 return -EPERM;
6817
6818 switch (fan_control_access_mode) {
6819 case TPACPI_FAN_WR_ACPI_SFAN:
6820 if (level >= 0 && level <= 7) {
6821 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
6822 return -EIO;
6823 } else
6824 return -EINVAL;
6825 break;
6826
6827 case TPACPI_FAN_WR_ACPI_FANS:
6828 case TPACPI_FAN_WR_TPEC:
6829 if (!(level & TP_EC_FAN_AUTO) &&
6830 !(level & TP_EC_FAN_FULLSPEED) &&
6831 ((level < 0) || (level > 7)))
6832 return -EINVAL;
6833
6834
6835
6836 if (level & TP_EC_FAN_FULLSPEED)
6837 level |= 7;
6838 else if (level & TP_EC_FAN_AUTO)
6839 level |= 4;
6840
6841 if (!acpi_ec_write(fan_status_offset, level))
6842 return -EIO;
6843 else
6844 tp_features.fan_ctrl_status_undef = 0;
6845 break;
6846
6847 default:
6848 return -ENXIO;
6849 }
6850
6851 vdbg_printk(TPACPI_DBG_FAN,
6852 "fan control: set fan control register to 0x%02x\n", level);
6853 return 0;
6854}
6855
6856static int fan_set_level_safe(int level)
6857{
6858 int rc;
6859
6860 if (!fan_control_allowed)
6861 return -EPERM;
6862
6863 if (mutex_lock_killable(&fan_mutex))
6864 return -ERESTARTSYS;
6865
6866 if (level == TPACPI_FAN_LAST_LEVEL)
6867 level = fan_control_desired_level;
6868
6869 rc = fan_set_level(level);
6870 if (!rc)
6871 fan_update_desired_level(level);
6872
6873 mutex_unlock(&fan_mutex);
6874 return rc;
6875}
6876
6877static int fan_set_enable(void)
6878{
6879 u8 s;
6880 int rc;
6881
6882 if (!fan_control_allowed)
6883 return -EPERM;
6884
6885 if (mutex_lock_killable(&fan_mutex))
6886 return -ERESTARTSYS;
6887
6888 switch (fan_control_access_mode) {
6889 case TPACPI_FAN_WR_ACPI_FANS:
6890 case TPACPI_FAN_WR_TPEC:
6891 rc = fan_get_status(&s);
6892 if (rc < 0)
6893 break;
6894
6895
6896 if (s != 7) {
6897 s &= 0x07;
6898 s |= TP_EC_FAN_AUTO | 4;
6899 }
6900
6901 if (!acpi_ec_write(fan_status_offset, s))
6902 rc = -EIO;
6903 else {
6904 tp_features.fan_ctrl_status_undef = 0;
6905 rc = 0;
6906 }
6907 break;
6908
6909 case TPACPI_FAN_WR_ACPI_SFAN:
6910 rc = fan_get_status(&s);
6911 if (rc < 0)
6912 break;
6913
6914 s &= 0x07;
6915
6916
6917 s |= 4;
6918
6919 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
6920 rc = -EIO;
6921 else
6922 rc = 0;
6923 break;
6924
6925 default:
6926 rc = -ENXIO;
6927 }
6928
6929 mutex_unlock(&fan_mutex);
6930
6931 if (!rc)
6932 vdbg_printk(TPACPI_DBG_FAN,
6933 "fan control: set fan control register to 0x%02x\n",
6934 s);
6935 return rc;
6936}
6937
6938static int fan_set_disable(void)
6939{
6940 int rc;
6941
6942 if (!fan_control_allowed)
6943 return -EPERM;
6944
6945 if (mutex_lock_killable(&fan_mutex))
6946 return -ERESTARTSYS;
6947
6948 rc = 0;
6949 switch (fan_control_access_mode) {
6950 case TPACPI_FAN_WR_ACPI_FANS:
6951 case TPACPI_FAN_WR_TPEC:
6952 if (!acpi_ec_write(fan_status_offset, 0x00))
6953 rc = -EIO;
6954 else {
6955 fan_control_desired_level = 0;
6956 tp_features.fan_ctrl_status_undef = 0;
6957 }
6958 break;
6959
6960 case TPACPI_FAN_WR_ACPI_SFAN:
6961 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
6962 rc = -EIO;
6963 else
6964 fan_control_desired_level = 0;
6965 break;
6966
6967 default:
6968 rc = -ENXIO;
6969 }
6970
6971 if (!rc)
6972 vdbg_printk(TPACPI_DBG_FAN,
6973 "fan control: set fan control register to 0\n");
6974
6975 mutex_unlock(&fan_mutex);
6976 return rc;
6977}
6978
6979static int fan_set_speed(int speed)
6980{
6981 int rc;
6982
6983 if (!fan_control_allowed)
6984 return -EPERM;
6985
6986 if (mutex_lock_killable(&fan_mutex))
6987 return -ERESTARTSYS;
6988
6989 rc = 0;
6990 switch (fan_control_access_mode) {
6991 case TPACPI_FAN_WR_ACPI_FANS:
6992 if (speed >= 0 && speed <= 65535) {
6993 if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
6994 speed, speed, speed))
6995 rc = -EIO;
6996 } else
6997 rc = -EINVAL;
6998 break;
6999
7000 default:
7001 rc = -ENXIO;
7002 }
7003
7004 mutex_unlock(&fan_mutex);
7005 return rc;
7006}
7007
7008static void fan_watchdog_reset(void)
7009{
7010 static int fan_watchdog_active;
7011
7012 if (fan_control_access_mode == TPACPI_FAN_WR_NONE)
7013 return;
7014
7015 if (fan_watchdog_active)
7016 cancel_delayed_work(&fan_watchdog_task);
7017
7018 if (fan_watchdog_maxinterval > 0 &&
7019 tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
7020 fan_watchdog_active = 1;
7021 if (!queue_delayed_work(tpacpi_wq, &fan_watchdog_task,
7022 msecs_to_jiffies(fan_watchdog_maxinterval
7023 * 1000))) {
7024 printk(TPACPI_ERR
7025 "failed to queue the fan watchdog, "
7026 "watchdog will not trigger\n");
7027 }
7028 } else
7029 fan_watchdog_active = 0;
7030}
7031
7032static void fan_watchdog_fire(struct work_struct *ignored)
7033{
7034 int rc;
7035
7036 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
7037 return;
7038
7039 printk(TPACPI_NOTICE "fan watchdog: enabling fan\n");
7040 rc = fan_set_enable();
7041 if (rc < 0) {
7042 printk(TPACPI_ERR "fan watchdog: error %d while enabling fan, "
7043 "will try again later...\n", -rc);
7044
7045 fan_watchdog_reset();
7046 }
7047}
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071static ssize_t fan_pwm1_enable_show(struct device *dev,
7072 struct device_attribute *attr,
7073 char *buf)
7074{
7075 int res, mode;
7076 u8 status;
7077
7078 res = fan_get_status_safe(&status);
7079 if (res)
7080 return res;
7081
7082 if (status & TP_EC_FAN_FULLSPEED) {
7083 mode = 0;
7084 } else if (status & TP_EC_FAN_AUTO) {
7085 mode = 2;
7086 } else
7087 mode = 1;
7088
7089 return snprintf(buf, PAGE_SIZE, "%d\n", mode);
7090}
7091
7092static ssize_t fan_pwm1_enable_store(struct device *dev,
7093 struct device_attribute *attr,
7094 const char *buf, size_t count)
7095{
7096 unsigned long t;
7097 int res, level;
7098
7099 if (parse_strtoul(buf, 2, &t))
7100 return -EINVAL;
7101
7102 tpacpi_disclose_usertask("hwmon pwm1_enable",
7103 "set fan mode to %lu\n", t);
7104
7105 switch (t) {
7106 case 0:
7107 level = TP_EC_FAN_FULLSPEED;
7108 break;
7109 case 1:
7110 level = TPACPI_FAN_LAST_LEVEL;
7111 break;
7112 case 2:
7113 level = TP_EC_FAN_AUTO;
7114 break;
7115 case 3:
7116
7117 return -ENOSYS;
7118 default:
7119 return -EINVAL;
7120 }
7121
7122 res = fan_set_level_safe(level);
7123 if (res == -ENXIO)
7124 return -EINVAL;
7125 else if (res < 0)
7126 return res;
7127
7128 fan_watchdog_reset();
7129
7130 return count;
7131}
7132
7133static struct device_attribute dev_attr_fan_pwm1_enable =
7134 __ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
7135 fan_pwm1_enable_show, fan_pwm1_enable_store);
7136
7137
7138static ssize_t fan_pwm1_show(struct device *dev,
7139 struct device_attribute *attr,
7140 char *buf)
7141{
7142 int res;
7143 u8 status;
7144
7145 res = fan_get_status_safe(&status);
7146 if (res)
7147 return res;
7148
7149 if ((status &
7150 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0)
7151 status = fan_control_desired_level;
7152
7153 if (status > 7)
7154 status = 7;
7155
7156 return snprintf(buf, PAGE_SIZE, "%u\n", (status * 255) / 7);
7157}
7158
7159static ssize_t fan_pwm1_store(struct device *dev,
7160 struct device_attribute *attr,
7161 const char *buf, size_t count)
7162{
7163 unsigned long s;
7164 int rc;
7165 u8 status, newlevel;
7166
7167 if (parse_strtoul(buf, 255, &s))
7168 return -EINVAL;
7169
7170 tpacpi_disclose_usertask("hwmon pwm1",
7171 "set fan speed to %lu\n", s);
7172
7173
7174 newlevel = (s >> 5) & 0x07;
7175
7176 if (mutex_lock_killable(&fan_mutex))
7177 return -ERESTARTSYS;
7178
7179 rc = fan_get_status(&status);
7180 if (!rc && (status &
7181 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) {
7182 rc = fan_set_level(newlevel);
7183 if (rc == -ENXIO)
7184 rc = -EINVAL;
7185 else if (!rc) {
7186 fan_update_desired_level(newlevel);
7187 fan_watchdog_reset();
7188 }
7189 }
7190
7191 mutex_unlock(&fan_mutex);
7192 return (rc)? rc : count;
7193}
7194
7195static struct device_attribute dev_attr_fan_pwm1 =
7196 __ATTR(pwm1, S_IWUSR | S_IRUGO,
7197 fan_pwm1_show, fan_pwm1_store);
7198
7199
7200static ssize_t fan_fan1_input_show(struct device *dev,
7201 struct device_attribute *attr,
7202 char *buf)
7203{
7204 int res;
7205 unsigned int speed;
7206
7207 res = fan_get_speed(&speed);
7208 if (res < 0)
7209 return res;
7210
7211 return snprintf(buf, PAGE_SIZE, "%u\n", speed);
7212}
7213
7214static struct device_attribute dev_attr_fan_fan1_input =
7215 __ATTR(fan1_input, S_IRUGO,
7216 fan_fan1_input_show, NULL);
7217
7218
7219static ssize_t fan_fan2_input_show(struct device *dev,
7220 struct device_attribute *attr,
7221 char *buf)
7222{
7223 int res;
7224 unsigned int speed;
7225
7226 res = fan2_get_speed(&speed);
7227 if (res < 0)
7228 return res;
7229
7230 return snprintf(buf, PAGE_SIZE, "%u\n", speed);
7231}
7232
7233static struct device_attribute dev_attr_fan_fan2_input =
7234 __ATTR(fan2_input, S_IRUGO,
7235 fan_fan2_input_show, NULL);
7236
7237
7238static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
7239 char *buf)
7240{
7241 return snprintf(buf, PAGE_SIZE, "%u\n", fan_watchdog_maxinterval);
7242}
7243
7244static ssize_t fan_fan_watchdog_store(struct device_driver *drv,
7245 const char *buf, size_t count)
7246{
7247 unsigned long t;
7248
7249 if (parse_strtoul(buf, 120, &t))
7250 return -EINVAL;
7251
7252 if (!fan_control_allowed)
7253 return -EPERM;
7254
7255 fan_watchdog_maxinterval = t;
7256 fan_watchdog_reset();
7257
7258 tpacpi_disclose_usertask("fan_watchdog", "set to %lu\n", t);
7259
7260 return count;
7261}
7262
7263static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO,
7264 fan_fan_watchdog_show, fan_fan_watchdog_store);
7265
7266
7267static struct attribute *fan_attributes[] = {
7268 &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr,
7269 &dev_attr_fan_fan1_input.attr,
7270 NULL,
7271 NULL
7272};
7273
7274static const struct attribute_group fan_attr_group = {
7275 .attrs = fan_attributes,
7276};
7277
7278#define TPACPI_FAN_Q1 0x0001
7279#define TPACPI_FAN_2FAN 0x0002
7280
7281#define TPACPI_FAN_QI(__id1, __id2, __quirks) \
7282 { .vendor = PCI_VENDOR_ID_IBM, \
7283 .bios = TPACPI_MATCH_ANY, \
7284 .ec = TPID(__id1, __id2), \
7285 .quirks = __quirks }
7286
7287#define TPACPI_FAN_QL(__id1, __id2, __quirks) \
7288 { .vendor = PCI_VENDOR_ID_LENOVO, \
7289 .bios = TPACPI_MATCH_ANY, \
7290 .ec = TPID(__id1, __id2), \
7291 .quirks = __quirks }
7292
7293static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
7294 TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1),
7295 TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1),
7296 TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1),
7297 TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1),
7298 TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN),
7299};
7300
7301#undef TPACPI_FAN_QL
7302#undef TPACPI_FAN_QI
7303
7304static int __init fan_init(struct ibm_init_struct *iibm)
7305{
7306 int rc;
7307 unsigned long quirks;
7308
7309 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
7310 "initializing fan subdriver\n");
7311
7312 mutex_init(&fan_mutex);
7313 fan_status_access_mode = TPACPI_FAN_NONE;
7314 fan_control_access_mode = TPACPI_FAN_WR_NONE;
7315 fan_control_commands = 0;
7316 fan_watchdog_maxinterval = 0;
7317 tp_features.fan_ctrl_status_undef = 0;
7318 tp_features.second_fan = 0;
7319 fan_control_desired_level = 7;
7320
7321 TPACPI_ACPIHANDLE_INIT(fans);
7322 TPACPI_ACPIHANDLE_INIT(gfan);
7323 TPACPI_ACPIHANDLE_INIT(sfan);
7324
7325 quirks = tpacpi_check_quirks(fan_quirk_table,
7326 ARRAY_SIZE(fan_quirk_table));
7327
7328 if (gfan_handle) {
7329
7330 fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
7331 } else {
7332
7333
7334 if (likely(acpi_ec_read(fan_status_offset,
7335 &fan_control_initial_status))) {
7336 fan_status_access_mode = TPACPI_FAN_RD_TPEC;
7337 if (quirks & TPACPI_FAN_Q1)
7338 fan_quirk1_setup();
7339 if (quirks & TPACPI_FAN_2FAN) {
7340 tp_features.second_fan = 1;
7341 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
7342 "secondary fan support enabled\n");
7343 }
7344 } else {
7345 printk(TPACPI_ERR
7346 "ThinkPad ACPI EC access misbehaving, "
7347 "fan status and control unavailable\n");
7348 return 1;
7349 }
7350 }
7351
7352 if (sfan_handle) {
7353
7354 fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN;
7355 fan_control_commands |=
7356 TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_ENABLE;
7357 } else {
7358 if (!gfan_handle) {
7359
7360
7361
7362 if (fans_handle) {
7363
7364 fan_control_access_mode =
7365 TPACPI_FAN_WR_ACPI_FANS;
7366 fan_control_commands |=
7367 TPACPI_FAN_CMD_SPEED |
7368 TPACPI_FAN_CMD_LEVEL |
7369 TPACPI_FAN_CMD_ENABLE;
7370 } else {
7371 fan_control_access_mode = TPACPI_FAN_WR_TPEC;
7372 fan_control_commands |=
7373 TPACPI_FAN_CMD_LEVEL |
7374 TPACPI_FAN_CMD_ENABLE;
7375 }
7376 }
7377 }
7378
7379 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
7380 "fan is %s, modes %d, %d\n",
7381 str_supported(fan_status_access_mode != TPACPI_FAN_NONE ||
7382 fan_control_access_mode != TPACPI_FAN_WR_NONE),
7383 fan_status_access_mode, fan_control_access_mode);
7384
7385
7386 if (!fan_control_allowed) {
7387 fan_control_access_mode = TPACPI_FAN_WR_NONE;
7388 fan_control_commands = 0;
7389 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
7390 "fan control features disabled by parameter\n");
7391 }
7392
7393
7394 if (fan_status_access_mode != TPACPI_FAN_NONE)
7395 fan_get_status_safe(NULL);
7396
7397 if (fan_status_access_mode != TPACPI_FAN_NONE ||
7398 fan_control_access_mode != TPACPI_FAN_WR_NONE) {
7399 if (tp_features.second_fan) {
7400
7401 fan_attributes[ARRAY_SIZE(fan_attributes)-2] =
7402 &dev_attr_fan_fan2_input.attr;
7403 }
7404 rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
7405 &fan_attr_group);
7406 if (rc < 0)
7407 return rc;
7408
7409 rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
7410 &driver_attr_fan_watchdog);
7411 if (rc < 0) {
7412 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
7413 &fan_attr_group);
7414 return rc;
7415 }
7416 return 0;
7417 } else
7418 return 1;
7419}
7420
7421static void fan_exit(void)
7422{
7423 vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_FAN,
7424 "cancelling any pending fan watchdog tasks\n");
7425
7426
7427 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group);
7428 driver_remove_file(&tpacpi_hwmon_pdriver.driver,
7429 &driver_attr_fan_watchdog);
7430
7431 cancel_delayed_work(&fan_watchdog_task);
7432 flush_workqueue(tpacpi_wq);
7433}
7434
7435static void fan_suspend(pm_message_t state)
7436{
7437 int rc;
7438
7439 if (!fan_control_allowed)
7440 return;
7441
7442
7443 fan_control_resume_level = 0;
7444 rc = fan_get_status_safe(&fan_control_resume_level);
7445 if (rc < 0)
7446 printk(TPACPI_NOTICE
7447 "failed to read fan level for later "
7448 "restore during resume: %d\n", rc);
7449
7450
7451
7452 if (tp_features.fan_ctrl_status_undef)
7453 fan_control_resume_level = 0;
7454}
7455
7456static void fan_resume(void)
7457{
7458 u8 current_level = 7;
7459 bool do_set = false;
7460 int rc;
7461
7462
7463 tp_features.fan_ctrl_status_undef = 0;
7464
7465 if (!fan_control_allowed ||
7466 !fan_control_resume_level ||
7467 (fan_get_status_safe(¤t_level) < 0))
7468 return;
7469
7470 switch (fan_control_access_mode) {
7471 case TPACPI_FAN_WR_ACPI_SFAN:
7472
7473 do_set = (fan_control_resume_level > current_level);
7474 break;
7475 case TPACPI_FAN_WR_ACPI_FANS:
7476 case TPACPI_FAN_WR_TPEC:
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492 if (fan_control_resume_level != 7 &&
7493 !(fan_control_resume_level & TP_EC_FAN_FULLSPEED))
7494 return;
7495 else
7496 do_set = !(current_level & TP_EC_FAN_FULLSPEED) &&
7497 (current_level != fan_control_resume_level);
7498 break;
7499 default:
7500 return;
7501 }
7502 if (do_set) {
7503 printk(TPACPI_NOTICE
7504 "restoring fan level to 0x%02x\n",
7505 fan_control_resume_level);
7506 rc = fan_set_level_safe(fan_control_resume_level);
7507 if (rc < 0)
7508 printk(TPACPI_NOTICE
7509 "failed to restore fan level: %d\n", rc);
7510 }
7511}
7512
7513static int fan_read(char *p)
7514{
7515 int len = 0;
7516 int rc;
7517 u8 status;
7518 unsigned int speed = 0;
7519
7520 switch (fan_status_access_mode) {
7521 case TPACPI_FAN_RD_ACPI_GFAN:
7522
7523 rc = fan_get_status_safe(&status);
7524 if (rc < 0)
7525 return rc;
7526
7527 len += sprintf(p + len, "status:\t\t%s\n"
7528 "level:\t\t%d\n",
7529 (status != 0) ? "enabled" : "disabled", status);
7530 break;
7531
7532 case TPACPI_FAN_RD_TPEC:
7533
7534 rc = fan_get_status_safe(&status);
7535 if (rc < 0)
7536 return rc;
7537
7538 len += sprintf(p + len, "status:\t\t%s\n",
7539 (status != 0) ? "enabled" : "disabled");
7540
7541 rc = fan_get_speed(&speed);
7542 if (rc < 0)
7543 return rc;
7544
7545 len += sprintf(p + len, "speed:\t\t%d\n", speed);
7546
7547 if (status & TP_EC_FAN_FULLSPEED)
7548
7549 len += sprintf(p + len, "level:\t\tdisengaged\n");
7550 else if (status & TP_EC_FAN_AUTO)
7551 len += sprintf(p + len, "level:\t\tauto\n");
7552 else
7553 len += sprintf(p + len, "level:\t\t%d\n", status);
7554 break;
7555
7556 case TPACPI_FAN_NONE:
7557 default:
7558 len += sprintf(p + len, "status:\t\tnot supported\n");
7559 }
7560
7561 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
7562 len += sprintf(p + len, "commands:\tlevel <level>");
7563
7564 switch (fan_control_access_mode) {
7565 case TPACPI_FAN_WR_ACPI_SFAN:
7566 len += sprintf(p + len, " (<level> is 0-7)\n");
7567 break;
7568
7569 default:
7570 len += sprintf(p + len, " (<level> is 0-7, "
7571 "auto, disengaged, full-speed)\n");
7572 break;
7573 }
7574 }
7575
7576 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
7577 len += sprintf(p + len, "commands:\tenable, disable\n"
7578 "commands:\twatchdog <timeout> (<timeout> "
7579 "is 0 (off), 1-120 (seconds))\n");
7580
7581 if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
7582 len += sprintf(p + len, "commands:\tspeed <speed>"
7583 " (<speed> is 0-65535)\n");
7584
7585 return len;
7586}
7587
7588static int fan_write_cmd_level(const char *cmd, int *rc)
7589{
7590 int level;
7591
7592 if (strlencmp(cmd, "level auto") == 0)
7593 level = TP_EC_FAN_AUTO;
7594 else if ((strlencmp(cmd, "level disengaged") == 0) |
7595 (strlencmp(cmd, "level full-speed") == 0))
7596 level = TP_EC_FAN_FULLSPEED;
7597 else if (sscanf(cmd, "level %d", &level) != 1)
7598 return 0;
7599
7600 *rc = fan_set_level_safe(level);
7601 if (*rc == -ENXIO)
7602 printk(TPACPI_ERR "level command accepted for unsupported "
7603 "access mode %d", fan_control_access_mode);
7604 else if (!*rc)
7605 tpacpi_disclose_usertask("procfs fan",
7606 "set level to %d\n", level);
7607
7608 return 1;
7609}
7610
7611static int fan_write_cmd_enable(const char *cmd, int *rc)
7612{
7613 if (strlencmp(cmd, "enable") != 0)
7614 return 0;
7615
7616 *rc = fan_set_enable();
7617 if (*rc == -ENXIO)
7618 printk(TPACPI_ERR "enable command accepted for unsupported "
7619 "access mode %d", fan_control_access_mode);
7620 else if (!*rc)
7621 tpacpi_disclose_usertask("procfs fan", "enable\n");
7622
7623 return 1;
7624}
7625
7626static int fan_write_cmd_disable(const char *cmd, int *rc)
7627{
7628 if (strlencmp(cmd, "disable") != 0)
7629 return 0;
7630
7631 *rc = fan_set_disable();
7632 if (*rc == -ENXIO)
7633 printk(TPACPI_ERR "disable command accepted for unsupported "
7634 "access mode %d", fan_control_access_mode);
7635 else if (!*rc)
7636 tpacpi_disclose_usertask("procfs fan", "disable\n");
7637
7638 return 1;
7639}
7640
7641static int fan_write_cmd_speed(const char *cmd, int *rc)
7642{
7643 int speed;
7644
7645
7646
7647
7648 if (sscanf(cmd, "speed %d", &speed) != 1)
7649 return 0;
7650
7651 *rc = fan_set_speed(speed);
7652 if (*rc == -ENXIO)
7653 printk(TPACPI_ERR "speed command accepted for unsupported "
7654 "access mode %d", fan_control_access_mode);
7655 else if (!*rc)
7656 tpacpi_disclose_usertask("procfs fan",
7657 "set speed to %d\n", speed);
7658
7659 return 1;
7660}
7661
7662static int fan_write_cmd_watchdog(const char *cmd, int *rc)
7663{
7664 int interval;
7665
7666 if (sscanf(cmd, "watchdog %d", &interval) != 1)
7667 return 0;
7668
7669 if (interval < 0 || interval > 120)
7670 *rc = -EINVAL;
7671 else {
7672 fan_watchdog_maxinterval = interval;
7673 tpacpi_disclose_usertask("procfs fan",
7674 "set watchdog timer to %d\n",
7675 interval);
7676 }
7677
7678 return 1;
7679}
7680
7681static int fan_write(char *buf)
7682{
7683 char *cmd;
7684 int rc = 0;
7685
7686 while (!rc && (cmd = next_cmd(&buf))) {
7687 if (!((fan_control_commands & TPACPI_FAN_CMD_LEVEL) &&
7688 fan_write_cmd_level(cmd, &rc)) &&
7689 !((fan_control_commands & TPACPI_FAN_CMD_ENABLE) &&
7690 (fan_write_cmd_enable(cmd, &rc) ||
7691 fan_write_cmd_disable(cmd, &rc) ||
7692 fan_write_cmd_watchdog(cmd, &rc))) &&
7693 !((fan_control_commands & TPACPI_FAN_CMD_SPEED) &&
7694 fan_write_cmd_speed(cmd, &rc))
7695 )
7696 rc = -EINVAL;
7697 else if (!rc)
7698 fan_watchdog_reset();
7699 }
7700
7701 return rc;
7702}
7703
7704static struct ibm_struct fan_driver_data = {
7705 .name = "fan",
7706 .read = fan_read,
7707 .write = fan_write,
7708 .exit = fan_exit,
7709 .suspend = fan_suspend,
7710 .resume = fan_resume,
7711};
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725static void tpacpi_driver_event(const unsigned int hkey_event)
7726{
7727}
7728
7729
7730
7731static void hotkey_driver_event(const unsigned int scancode)
7732{
7733 tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode);
7734}
7735
7736
7737static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev,
7738 struct device_attribute *attr,
7739 char *buf)
7740{
7741 return snprintf(buf, PAGE_SIZE, "%s\n", TPACPI_NAME);
7742}
7743
7744static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
7745 __ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL);
7746
7747
7748
7749
7750static struct proc_dir_entry *proc_dir;
7751
7752
7753
7754
7755
7756static int force_load;
7757
7758#ifdef CONFIG_THINKPAD_ACPI_DEBUG
7759static const char * __init str_supported(int is_supported)
7760{
7761 static char text_unsupported[] __initdata = "not supported";
7762
7763 return (is_supported)? &text_unsupported[4] : &text_unsupported[0];
7764}
7765#endif
7766
7767static void ibm_exit(struct ibm_struct *ibm)
7768{
7769 dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name);
7770
7771 list_del_init(&ibm->all_drivers);
7772
7773 if (ibm->flags.acpi_notify_installed) {
7774 dbg_printk(TPACPI_DBG_EXIT,
7775 "%s: acpi_remove_notify_handler\n", ibm->name);
7776 BUG_ON(!ibm->acpi);
7777 acpi_remove_notify_handler(*ibm->acpi->handle,
7778 ibm->acpi->type,
7779 dispatch_acpi_notify);
7780 ibm->flags.acpi_notify_installed = 0;
7781 ibm->flags.acpi_notify_installed = 0;
7782 }
7783
7784 if (ibm->flags.proc_created) {
7785 dbg_printk(TPACPI_DBG_EXIT,
7786 "%s: remove_proc_entry\n", ibm->name);
7787 remove_proc_entry(ibm->name, proc_dir);
7788 ibm->flags.proc_created = 0;
7789 }
7790
7791 if (ibm->flags.acpi_driver_registered) {
7792 dbg_printk(TPACPI_DBG_EXIT,
7793 "%s: acpi_bus_unregister_driver\n", ibm->name);
7794 BUG_ON(!ibm->acpi);
7795 acpi_bus_unregister_driver(ibm->acpi->driver);
7796 kfree(ibm->acpi->driver);
7797 ibm->acpi->driver = NULL;
7798 ibm->flags.acpi_driver_registered = 0;
7799 }
7800
7801 if (ibm->flags.init_called && ibm->exit) {
7802 ibm->exit();
7803 ibm->flags.init_called = 0;
7804 }
7805
7806 dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name);
7807}
7808
7809static int __init ibm_init(struct ibm_init_struct *iibm)
7810{
7811 int ret;
7812 struct ibm_struct *ibm = iibm->data;
7813 struct proc_dir_entry *entry;
7814
7815 BUG_ON(ibm == NULL);
7816
7817 INIT_LIST_HEAD(&ibm->all_drivers);
7818
7819 if (ibm->flags.experimental && !experimental)
7820 return 0;
7821
7822 dbg_printk(TPACPI_DBG_INIT,
7823 "probing for %s\n", ibm->name);
7824
7825 if (iibm->init) {
7826 ret = iibm->init(iibm);
7827 if (ret > 0)
7828 return 0;
7829 if (ret)
7830 return ret;
7831
7832 ibm->flags.init_called = 1;
7833 }
7834
7835 if (ibm->acpi) {
7836 if (ibm->acpi->hid) {
7837 ret = register_tpacpi_subdriver(ibm);
7838 if (ret)
7839 goto err_out;
7840 }
7841
7842 if (ibm->acpi->notify) {
7843 ret = setup_acpi_notify(ibm);
7844 if (ret == -ENODEV) {
7845 printk(TPACPI_NOTICE "disabling subdriver %s\n",
7846 ibm->name);
7847 ret = 0;
7848 goto err_out;
7849 }
7850 if (ret < 0)
7851 goto err_out;
7852 }
7853 }
7854
7855 dbg_printk(TPACPI_DBG_INIT,
7856 "%s installed\n", ibm->name);
7857
7858 if (ibm->read) {
7859 entry = create_proc_entry(ibm->name,
7860 S_IFREG | S_IRUGO | S_IWUSR,
7861 proc_dir);
7862 if (!entry) {
7863 printk(TPACPI_ERR "unable to create proc entry %s\n",
7864 ibm->name);
7865 ret = -ENODEV;
7866 goto err_out;
7867 }
7868 entry->data = ibm;
7869 entry->read_proc = &dispatch_procfs_read;
7870 if (ibm->write)
7871 entry->write_proc = &dispatch_procfs_write;
7872 ibm->flags.proc_created = 1;
7873 }
7874
7875 list_add_tail(&ibm->all_drivers, &tpacpi_all_drivers);
7876
7877 return 0;
7878
7879err_out:
7880 dbg_printk(TPACPI_DBG_INIT,
7881 "%s: at error exit path with result %d\n",
7882 ibm->name, ret);
7883
7884 ibm_exit(ibm);
7885 return (ret < 0)? ret : 0;
7886}
7887
7888
7889
7890static bool __pure __init tpacpi_is_fw_digit(const char c)
7891{
7892 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z');
7893}
7894
7895
7896static bool __pure __init tpacpi_is_valid_fw_id(const char* const s,
7897 const char t)
7898{
7899 return s && strlen(s) >= 8 &&
7900 tpacpi_is_fw_digit(s[0]) &&
7901 tpacpi_is_fw_digit(s[1]) &&
7902 s[2] == t && s[3] == 'T' &&
7903 tpacpi_is_fw_digit(s[4]) &&
7904 tpacpi_is_fw_digit(s[5]) &&
7905 s[6] == 'W' && s[7] == 'W';
7906}
7907
7908
7909
7910
7911static int __must_check __init get_thinkpad_model_data(
7912 struct thinkpad_id_data *tp)
7913{
7914 const struct dmi_device *dev = NULL;
7915 char ec_fw_string[18];
7916 char const *s;
7917
7918 if (!tp)
7919 return -EINVAL;
7920
7921 memset(tp, 0, sizeof(*tp));
7922
7923 if (dmi_name_in_vendors("IBM"))
7924 tp->vendor = PCI_VENDOR_ID_IBM;
7925 else if (dmi_name_in_vendors("LENOVO"))
7926 tp->vendor = PCI_VENDOR_ID_LENOVO;
7927 else
7928 return 0;
7929
7930 s = dmi_get_system_info(DMI_BIOS_VERSION);
7931 tp->bios_version_str = kstrdup(s, GFP_KERNEL);
7932 if (s && !tp->bios_version_str)
7933 return -ENOMEM;
7934
7935
7936 if (!tpacpi_is_valid_fw_id(tp->bios_version_str, 'E'))
7937 return 0;
7938
7939 tp->bios_model = tp->bios_version_str[0]
7940 | (tp->bios_version_str[1] << 8);
7941 tp->bios_release = (tp->bios_version_str[4] << 8)
7942 | tp->bios_version_str[5];
7943
7944
7945
7946
7947
7948
7949
7950
7951 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
7952 if (sscanf(dev->name,
7953 "IBM ThinkPad Embedded Controller -[%17c",
7954 ec_fw_string) == 1) {
7955 ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
7956 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
7957
7958 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
7959 if (!tp->ec_version_str)
7960 return -ENOMEM;
7961
7962 if (tpacpi_is_valid_fw_id(ec_fw_string, 'H')) {
7963 tp->ec_model = ec_fw_string[0]
7964 | (ec_fw_string[1] << 8);
7965 tp->ec_release = (ec_fw_string[4] << 8)
7966 | ec_fw_string[5];
7967 } else {
7968 printk(TPACPI_NOTICE
7969 "ThinkPad firmware release %s "
7970 "doesn't match the known patterns\n",
7971 ec_fw_string);
7972 printk(TPACPI_NOTICE
7973 "please report this to %s\n",
7974 TPACPI_MAIL);
7975 }
7976 break;
7977 }
7978 }
7979
7980 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
7981 if (s && !strnicmp(s, "ThinkPad", 8)) {
7982 tp->model_str = kstrdup(s, GFP_KERNEL);
7983 if (!tp->model_str)
7984 return -ENOMEM;
7985 }
7986
7987 s = dmi_get_system_info(DMI_PRODUCT_NAME);
7988 tp->nummodel_str = kstrdup(s, GFP_KERNEL);
7989 if (s && !tp->nummodel_str)
7990 return -ENOMEM;
7991
7992 return 0;
7993}
7994
7995static int __init probe_for_thinkpad(void)
7996{
7997 int is_thinkpad;
7998
7999 if (acpi_disabled)
8000 return -ENODEV;
8001
8002
8003
8004
8005
8006 is_thinkpad = (thinkpad_id.model_str != NULL) ||
8007 (thinkpad_id.ec_model != 0) ||
8008 tpacpi_is_fw_known();
8009
8010
8011 TPACPI_ACPIHANDLE_INIT(ec);
8012 if (!ec_handle) {
8013 if (is_thinkpad)
8014 printk(TPACPI_ERR
8015 "Not yet supported ThinkPad detected!\n");
8016 return -ENODEV;
8017 }
8018
8019 if (!is_thinkpad && !force_load)
8020 return -ENODEV;
8021
8022 return 0;
8023}
8024
8025
8026
8027
8028static struct ibm_init_struct ibms_init[] __initdata = {
8029 {
8030 .init = thinkpad_acpi_driver_init,
8031 .data = &thinkpad_acpi_driver_data,
8032 },
8033 {
8034 .init = hotkey_init,
8035 .data = &hotkey_driver_data,
8036 },
8037 {
8038 .init = bluetooth_init,
8039 .data = &bluetooth_driver_data,
8040 },
8041 {
8042 .init = wan_init,
8043 .data = &wan_driver_data,
8044 },
8045 {
8046 .init = uwb_init,
8047 .data = &uwb_driver_data,
8048 },
8049#ifdef CONFIG_THINKPAD_ACPI_VIDEO
8050 {
8051 .init = video_init,
8052 .data = &video_driver_data,
8053 },
8054#endif
8055 {
8056 .init = light_init,
8057 .data = &light_driver_data,
8058 },
8059 {
8060 .init = cmos_init,
8061 .data = &cmos_driver_data,
8062 },
8063 {
8064 .init = led_init,
8065 .data = &led_driver_data,
8066 },
8067 {
8068 .init = beep_init,
8069 .data = &beep_driver_data,
8070 },
8071 {
8072 .init = thermal_init,
8073 .data = &thermal_driver_data,
8074 },
8075 {
8076 .data = &ecdump_driver_data,
8077 },
8078 {
8079 .init = brightness_init,
8080 .data = &brightness_driver_data,
8081 },
8082 {
8083 .data = &volume_driver_data,
8084 },
8085 {
8086 .init = fan_init,
8087 .data = &fan_driver_data,
8088 },
8089};
8090
8091static int __init set_ibm_param(const char *val, struct kernel_param *kp)
8092{
8093 unsigned int i;
8094 struct ibm_struct *ibm;
8095
8096 if (!kp || !kp->name || !val)
8097 return -EINVAL;
8098
8099 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
8100 ibm = ibms_init[i].data;
8101 WARN_ON(ibm == NULL);
8102
8103 if (!ibm || !ibm->name)
8104 continue;
8105
8106 if (strcmp(ibm->name, kp->name) == 0 && ibm->write) {
8107 if (strlen(val) > sizeof(ibms_init[i].param) - 2)
8108 return -ENOSPC;
8109 strcpy(ibms_init[i].param, val);
8110 strcat(ibms_init[i].param, ",");
8111 return 0;
8112 }
8113 }
8114
8115 return -EINVAL;
8116}
8117
8118module_param(experimental, int, 0);
8119MODULE_PARM_DESC(experimental,
8120 "Enables experimental features when non-zero");
8121
8122module_param_named(debug, dbg_level, uint, 0);
8123MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
8124
8125module_param(force_load, bool, 0);
8126MODULE_PARM_DESC(force_load,
8127 "Attempts to load the driver even on a "
8128 "mis-identified ThinkPad when true");
8129
8130module_param_named(fan_control, fan_control_allowed, bool, 0);
8131MODULE_PARM_DESC(fan_control,
8132 "Enables setting fan parameters features when true");
8133
8134module_param_named(brightness_mode, brightness_mode, uint, 0);
8135MODULE_PARM_DESC(brightness_mode,
8136 "Selects brightness control strategy: "
8137 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
8138
8139module_param(brightness_enable, uint, 0);
8140MODULE_PARM_DESC(brightness_enable,
8141 "Enables backlight control when 1, disables when 0");
8142
8143module_param(hotkey_report_mode, uint, 0);
8144MODULE_PARM_DESC(hotkey_report_mode,
8145 "used for backwards compatibility with userspace, "
8146 "see documentation");
8147
8148#define TPACPI_PARAM(feature) \
8149 module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
8150 MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \
8151 "at module load, see documentation")
8152
8153TPACPI_PARAM(hotkey);
8154TPACPI_PARAM(bluetooth);
8155TPACPI_PARAM(video);
8156TPACPI_PARAM(light);
8157TPACPI_PARAM(cmos);
8158TPACPI_PARAM(led);
8159TPACPI_PARAM(beep);
8160TPACPI_PARAM(ecdump);
8161TPACPI_PARAM(brightness);
8162TPACPI_PARAM(volume);
8163TPACPI_PARAM(fan);
8164
8165#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
8166module_param(dbg_wlswemul, uint, 0);
8167MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
8168module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
8169MODULE_PARM_DESC(wlsw_state,
8170 "Initial state of the emulated WLSW switch");
8171
8172module_param(dbg_bluetoothemul, uint, 0);
8173MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
8174module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
8175MODULE_PARM_DESC(bluetooth_state,
8176 "Initial state of the emulated bluetooth switch");
8177
8178module_param(dbg_wwanemul, uint, 0);
8179MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
8180module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
8181MODULE_PARM_DESC(wwan_state,
8182 "Initial state of the emulated WWAN switch");
8183
8184module_param(dbg_uwbemul, uint, 0);
8185MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
8186module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
8187MODULE_PARM_DESC(uwb_state,
8188 "Initial state of the emulated UWB switch");
8189#endif
8190
8191static void thinkpad_acpi_module_exit(void)
8192{
8193 struct ibm_struct *ibm, *itmp;
8194
8195 tpacpi_lifecycle = TPACPI_LIFE_EXITING;
8196
8197 list_for_each_entry_safe_reverse(ibm, itmp,
8198 &tpacpi_all_drivers,
8199 all_drivers) {
8200 ibm_exit(ibm);
8201 }
8202
8203 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
8204
8205 if (tpacpi_inputdev) {
8206 if (tp_features.input_device_registered)
8207 input_unregister_device(tpacpi_inputdev);
8208 else
8209 input_free_device(tpacpi_inputdev);
8210 }
8211
8212 if (tpacpi_hwmon)
8213 hwmon_device_unregister(tpacpi_hwmon);
8214
8215 if (tp_features.sensors_pdev_attrs_registered)
8216 device_remove_file(&tpacpi_sensors_pdev->dev,
8217 &dev_attr_thinkpad_acpi_pdev_name);
8218 if (tpacpi_sensors_pdev)
8219 platform_device_unregister(tpacpi_sensors_pdev);
8220 if (tpacpi_pdev)
8221 platform_device_unregister(tpacpi_pdev);
8222
8223 if (tp_features.sensors_pdrv_attrs_registered)
8224 tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver);
8225 if (tp_features.platform_drv_attrs_registered)
8226 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
8227
8228 if (tp_features.sensors_pdrv_registered)
8229 platform_driver_unregister(&tpacpi_hwmon_pdriver);
8230
8231 if (tp_features.platform_drv_registered)
8232 platform_driver_unregister(&tpacpi_pdriver);
8233
8234 if (proc_dir)
8235 remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir);
8236
8237 if (tpacpi_wq)
8238 destroy_workqueue(tpacpi_wq);
8239
8240 kfree(thinkpad_id.bios_version_str);
8241 kfree(thinkpad_id.ec_version_str);
8242 kfree(thinkpad_id.model_str);
8243}
8244
8245
8246static int __init thinkpad_acpi_module_init(void)
8247{
8248 int ret, i;
8249
8250 tpacpi_lifecycle = TPACPI_LIFE_INIT;
8251
8252
8253 if (hotkey_report_mode > 2)
8254 return -EINVAL;
8255
8256
8257
8258 ret = get_thinkpad_model_data(&thinkpad_id);
8259 if (ret) {
8260 printk(TPACPI_ERR
8261 "unable to get DMI data: %d\n", ret);
8262 thinkpad_acpi_module_exit();
8263 return ret;
8264 }
8265 ret = probe_for_thinkpad();
8266 if (ret) {
8267 thinkpad_acpi_module_exit();
8268 return ret;
8269 }
8270
8271
8272
8273 TPACPI_ACPIHANDLE_INIT(ecrd);
8274 TPACPI_ACPIHANDLE_INIT(ecwr);
8275
8276 tpacpi_wq = create_singlethread_workqueue(TPACPI_WORKQUEUE_NAME);
8277 if (!tpacpi_wq) {
8278 thinkpad_acpi_module_exit();
8279 return -ENOMEM;
8280 }
8281
8282 proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir);
8283 if (!proc_dir) {
8284 printk(TPACPI_ERR
8285 "unable to create proc dir " TPACPI_PROC_DIR);
8286 thinkpad_acpi_module_exit();
8287 return -ENODEV;
8288 }
8289
8290 ret = platform_driver_register(&tpacpi_pdriver);
8291 if (ret) {
8292 printk(TPACPI_ERR
8293 "unable to register main platform driver\n");
8294 thinkpad_acpi_module_exit();
8295 return ret;
8296 }
8297 tp_features.platform_drv_registered = 1;
8298
8299 ret = platform_driver_register(&tpacpi_hwmon_pdriver);
8300 if (ret) {
8301 printk(TPACPI_ERR
8302 "unable to register hwmon platform driver\n");
8303 thinkpad_acpi_module_exit();
8304 return ret;
8305 }
8306 tp_features.sensors_pdrv_registered = 1;
8307
8308 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
8309 if (!ret) {
8310 tp_features.platform_drv_attrs_registered = 1;
8311 ret = tpacpi_create_driver_attributes(
8312 &tpacpi_hwmon_pdriver.driver);
8313 }
8314 if (ret) {
8315 printk(TPACPI_ERR
8316 "unable to create sysfs driver attributes\n");
8317 thinkpad_acpi_module_exit();
8318 return ret;
8319 }
8320 tp_features.sensors_pdrv_attrs_registered = 1;
8321
8322
8323
8324 tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, -1,
8325 NULL, 0);
8326 if (IS_ERR(tpacpi_pdev)) {
8327 ret = PTR_ERR(tpacpi_pdev);
8328 tpacpi_pdev = NULL;
8329 printk(TPACPI_ERR "unable to register platform device\n");
8330 thinkpad_acpi_module_exit();
8331 return ret;
8332 }
8333 tpacpi_sensors_pdev = platform_device_register_simple(
8334 TPACPI_HWMON_DRVR_NAME,
8335 -1, NULL, 0);
8336 if (IS_ERR(tpacpi_sensors_pdev)) {
8337 ret = PTR_ERR(tpacpi_sensors_pdev);
8338 tpacpi_sensors_pdev = NULL;
8339 printk(TPACPI_ERR
8340 "unable to register hwmon platform device\n");
8341 thinkpad_acpi_module_exit();
8342 return ret;
8343 }
8344 ret = device_create_file(&tpacpi_sensors_pdev->dev,
8345 &dev_attr_thinkpad_acpi_pdev_name);
8346 if (ret) {
8347 printk(TPACPI_ERR
8348 "unable to create sysfs hwmon device attributes\n");
8349 thinkpad_acpi_module_exit();
8350 return ret;
8351 }
8352 tp_features.sensors_pdev_attrs_registered = 1;
8353 tpacpi_hwmon = hwmon_device_register(&tpacpi_sensors_pdev->dev);
8354 if (IS_ERR(tpacpi_hwmon)) {
8355 ret = PTR_ERR(tpacpi_hwmon);
8356 tpacpi_hwmon = NULL;
8357 printk(TPACPI_ERR "unable to register hwmon device\n");
8358 thinkpad_acpi_module_exit();
8359 return ret;
8360 }
8361 mutex_init(&tpacpi_inputdev_send_mutex);
8362 tpacpi_inputdev = input_allocate_device();
8363 if (!tpacpi_inputdev) {
8364 printk(TPACPI_ERR "unable to allocate input device\n");
8365 thinkpad_acpi_module_exit();
8366 return -ENOMEM;
8367 } else {
8368
8369 tpacpi_inputdev->name = "ThinkPad Extra Buttons";
8370 tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0";
8371 tpacpi_inputdev->id.bustype = BUS_HOST;
8372 tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ?
8373 thinkpad_id.vendor :
8374 PCI_VENDOR_ID_IBM;
8375 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
8376 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
8377 }
8378 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
8379 ret = ibm_init(&ibms_init[i]);
8380 if (ret >= 0 && *ibms_init[i].param)
8381 ret = ibms_init[i].data->write(ibms_init[i].param);
8382 if (ret < 0) {
8383 thinkpad_acpi_module_exit();
8384 return ret;
8385 }
8386 }
8387 ret = input_register_device(tpacpi_inputdev);
8388 if (ret < 0) {
8389 printk(TPACPI_ERR "unable to register input device\n");
8390 thinkpad_acpi_module_exit();
8391 return ret;
8392 } else {
8393 tp_features.input_device_registered = 1;
8394 }
8395
8396 tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
8397 return 0;
8398}
8399
8400MODULE_ALIAS(TPACPI_DRVR_SHORTNAME);
8401
8402
8403
8404
8405
8406
8407
8408
8409MODULE_DEVICE_TABLE(acpi, ibm_htk_device_ids);
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420#define IBM_BIOS_MODULE_ALIAS(__type) \
8421 MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*")
8422
8423
8424
8425
8426IBM_BIOS_MODULE_ALIAS("I[MU]");
8427
8428MODULE_AUTHOR("Borislav Deianov <borislav@users.sf.net>");
8429MODULE_AUTHOR("Henrique de Moraes Holschuh <hmh@hmh.eng.br>");
8430MODULE_DESCRIPTION(TPACPI_DESC);
8431MODULE_VERSION(TPACPI_VERSION);
8432MODULE_LICENSE("GPL");
8433
8434module_init(thinkpad_acpi_module_init);
8435module_exit(thinkpad_acpi_module_exit);
8436