aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-12-16 00:00:54 -0500
committerLen Brown <len.brown@intel.com>2009-12-16 00:00:54 -0500
commit7458bbd044f0e799ad27c3fc71e1115ac30a9c25 (patch)
tree4c9a320613722421f49b53266abcc64f90471f91 /drivers/platform
parent1667e399a41be976c9d37bf02aa477979df111d2 (diff)
parent5d2eb14d36723eba0b31ae208bc346835751e944 (diff)
Merge branch 'thinkpad-2.6.33' into release
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c1178
1 files changed, 899 insertions, 279 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index cf61d6a8ef6f..448c8aeb166b 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -21,8 +21,8 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#define TPACPI_VERSION "0.23" 24#define TPACPI_VERSION "0.24"
25#define TPACPI_SYSFS_VERSION 0x020500 25#define TPACPI_SYSFS_VERSION 0x020700
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -61,6 +61,7 @@
61 61
62#include <linux/nvram.h> 62#include <linux/nvram.h>
63#include <linux/proc_fs.h> 63#include <linux/proc_fs.h>
64#include <linux/seq_file.h>
64#include <linux/sysfs.h> 65#include <linux/sysfs.h>
65#include <linux/backlight.h> 66#include <linux/backlight.h>
66#include <linux/fb.h> 67#include <linux/fb.h>
@@ -76,6 +77,10 @@
76#include <linux/jiffies.h> 77#include <linux/jiffies.h>
77#include <linux/workqueue.h> 78#include <linux/workqueue.h>
78 79
80#include <sound/core.h>
81#include <sound/control.h>
82#include <sound/initval.h>
83
79#include <acpi/acpi_drivers.h> 84#include <acpi/acpi_drivers.h>
80 85
81#include <linux/pci_ids.h> 86#include <linux/pci_ids.h>
@@ -231,6 +236,7 @@ enum tpacpi_hkey_event_t {
231#define TPACPI_DBG_HKEY 0x0008 236#define TPACPI_DBG_HKEY 0x0008
232#define TPACPI_DBG_FAN 0x0010 237#define TPACPI_DBG_FAN 0x0010
233#define TPACPI_DBG_BRGHT 0x0020 238#define TPACPI_DBG_BRGHT 0x0020
239#define TPACPI_DBG_MIXER 0x0040
234 240
235#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") 241#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
236#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") 242#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
@@ -256,7 +262,7 @@ struct tp_acpi_drv_struct {
256struct ibm_struct { 262struct ibm_struct {
257 char *name; 263 char *name;
258 264
259 int (*read) (char *); 265 int (*read) (struct seq_file *);
260 int (*write) (char *); 266 int (*write) (char *);
261 void (*exit) (void); 267 void (*exit) (void);
262 void (*resume) (void); 268 void (*resume) (void);
@@ -298,6 +304,7 @@ static struct {
298 u32 fan_ctrl_status_undef:1; 304 u32 fan_ctrl_status_undef:1;
299 u32 second_fan:1; 305 u32 second_fan:1;
300 u32 beep_needs_two_args:1; 306 u32 beep_needs_two_args:1;
307 u32 mixer_no_level_control:1;
301 u32 input_device_registered:1; 308 u32 input_device_registered:1;
302 u32 platform_drv_registered:1; 309 u32 platform_drv_registered:1;
303 u32 platform_drv_attrs_registered:1; 310 u32 platform_drv_attrs_registered:1;
@@ -309,6 +316,7 @@ static struct {
309 316
310static struct { 317static struct {
311 u16 hotkey_mask_ff:1; 318 u16 hotkey_mask_ff:1;
319 u16 volume_ctrl_forbidden:1;
312} tp_warned; 320} tp_warned;
313 321
314struct thinkpad_id_data { 322struct thinkpad_id_data {
@@ -425,6 +433,12 @@ static void tpacpi_log_usertask(const char * const what)
425 .ec = TPACPI_MATCH_ANY, \ 433 .ec = TPACPI_MATCH_ANY, \
426 .quirks = (__quirk) } 434 .quirks = (__quirk) }
427 435
436#define TPACPI_QEC_LNV(__id1, __id2, __quirk) \
437 { .vendor = PCI_VENDOR_ID_LENOVO, \
438 .bios = TPACPI_MATCH_ANY, \
439 .ec = TPID(__id1, __id2), \
440 .quirks = (__quirk) }
441
428struct tpacpi_quirk { 442struct tpacpi_quirk {
429 unsigned int vendor; 443 unsigned int vendor;
430 u16 bios; 444 u16 bios;
@@ -776,36 +790,25 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
776 **************************************************************************** 790 ****************************************************************************
777 ****************************************************************************/ 791 ****************************************************************************/
778 792
779static int dispatch_procfs_read(char *page, char **start, off_t off, 793static int dispatch_proc_show(struct seq_file *m, void *v)
780 int count, int *eof, void *data)
781{ 794{
782 struct ibm_struct *ibm = data; 795 struct ibm_struct *ibm = m->private;
783 int len;
784 796
785 if (!ibm || !ibm->read) 797 if (!ibm || !ibm->read)
786 return -EINVAL; 798 return -EINVAL;
799 return ibm->read(m);
800}
787 801
788 len = ibm->read(page); 802static int dispatch_proc_open(struct inode *inode, struct file *file)
789 if (len < 0) 803{
790 return len; 804 return single_open(file, dispatch_proc_show, PDE(inode)->data);
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} 805}
803 806
804static int dispatch_procfs_write(struct file *file, 807static ssize_t dispatch_proc_write(struct file *file,
805 const char __user *userbuf, 808 const char __user *userbuf,
806 unsigned long count, void *data) 809 size_t count, loff_t *pos)
807{ 810{
808 struct ibm_struct *ibm = data; 811 struct ibm_struct *ibm = PDE(file->f_path.dentry->d_inode)->data;
809 char *kernbuf; 812 char *kernbuf;
810 int ret; 813 int ret;
811 814
@@ -834,6 +837,15 @@ static int dispatch_procfs_write(struct file *file,
834 return ret; 837 return ret;
835} 838}
836 839
840static const struct file_operations dispatch_proc_fops = {
841 .owner = THIS_MODULE,
842 .open = dispatch_proc_open,
843 .read = seq_read,
844 .llseek = seq_lseek,
845 .release = single_release,
846 .write = dispatch_proc_write,
847};
848
837static char *next_cmd(char **cmds) 849static char *next_cmd(char **cmds)
838{ 850{
839 char *start = *cmds; 851 char *start = *cmds;
@@ -1261,6 +1273,7 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1261 struct tpacpi_rfk *atp_rfk; 1273 struct tpacpi_rfk *atp_rfk;
1262 int res; 1274 int res;
1263 bool sw_state = false; 1275 bool sw_state = false;
1276 bool hw_state;
1264 int sw_status; 1277 int sw_status;
1265 1278
1266 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); 1279 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
@@ -1295,7 +1308,8 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1295 rfkill_init_sw_state(atp_rfk->rfkill, sw_state); 1308 rfkill_init_sw_state(atp_rfk->rfkill, sw_state);
1296 } 1309 }
1297 } 1310 }
1298 rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); 1311 hw_state = tpacpi_rfk_check_hwblock_state();
1312 rfkill_set_hw_state(atp_rfk->rfkill, hw_state);
1299 1313
1300 res = rfkill_register(atp_rfk->rfkill); 1314 res = rfkill_register(atp_rfk->rfkill);
1301 if (res < 0) { 1315 if (res < 0) {
@@ -1308,6 +1322,9 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1308 } 1322 }
1309 1323
1310 tpacpi_rfkill_switches[id] = atp_rfk; 1324 tpacpi_rfkill_switches[id] = atp_rfk;
1325
1326 printk(TPACPI_INFO "rfkill switch %s: radio is %sblocked\n",
1327 name, (sw_state || hw_state) ? "" : "un");
1311 return 0; 1328 return 0;
1312} 1329}
1313 1330
@@ -1380,12 +1397,10 @@ static ssize_t tpacpi_rfk_sysfs_enable_store(const enum tpacpi_rfk_id id,
1380} 1397}
1381 1398
1382/* procfs -------------------------------------------------------------- */ 1399/* procfs -------------------------------------------------------------- */
1383static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p) 1400static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, struct seq_file *m)
1384{ 1401{
1385 int len = 0;
1386
1387 if (id >= TPACPI_RFK_SW_MAX) 1402 if (id >= TPACPI_RFK_SW_MAX)
1388 len += sprintf(p + len, "status:\t\tnot supported\n"); 1403 seq_printf(m, "status:\t\tnot supported\n");
1389 else { 1404 else {
1390 int status; 1405 int status;
1391 1406
@@ -1399,13 +1414,13 @@ static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p)
1399 return status; 1414 return status;
1400 } 1415 }
1401 1416
1402 len += sprintf(p + len, "status:\t\t%s\n", 1417 seq_printf(m, "status:\t\t%s\n",
1403 (status == TPACPI_RFK_RADIO_ON) ? 1418 (status == TPACPI_RFK_RADIO_ON) ?
1404 "enabled" : "disabled"); 1419 "enabled" : "disabled");
1405 len += sprintf(p + len, "commands:\tenable, disable\n"); 1420 seq_printf(m, "commands:\tenable, disable\n");
1406 } 1421 }
1407 1422
1408 return len; 1423 return 0;
1409} 1424}
1410 1425
1411static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf) 1426static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf)
@@ -1776,7 +1791,7 @@ static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1776 1791
1777 TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */ 1792 TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */
1778 TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */ 1793 TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */
1779 TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */ 1794 TPV_QL1('7', 'E', 'D', '0', '1', '5'), /* R60e, R60i */
1780 1795
1781 /* BIOS FW BIOS VERS EC FW EC VERS */ 1796 /* BIOS FW BIOS VERS EC FW EC VERS */
1782 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */ 1797 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */
@@ -1792,8 +1807,8 @@ static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1792 TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */ 1807 TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */
1793 TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */ 1808 TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */
1794 1809
1795 TPV_QL0('7', 'B', 'D', '7'), /* X60/s */ 1810 TPV_QL1('7', 'B', 'D', '7', '4', '0'), /* X60/s */
1796 TPV_QL0('7', 'J', '3', '0'), /* X60t */ 1811 TPV_QL1('7', 'J', '3', '0', '1', '3'), /* X60t */
1797 1812
1798 /* (0) - older versions lack DMI EC fw string and functionality */ 1813 /* (0) - older versions lack DMI EC fw string and functionality */
1799 /* (1) - older versions known to lack functionality */ 1814 /* (1) - older versions known to lack functionality */
@@ -1883,14 +1898,11 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
1883 return 0; 1898 return 0;
1884} 1899}
1885 1900
1886static int thinkpad_acpi_driver_read(char *p) 1901static int thinkpad_acpi_driver_read(struct seq_file *m)
1887{ 1902{
1888 int len = 0; 1903 seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC);
1889 1904 seq_printf(m, "version:\t%s\n", TPACPI_VERSION);
1890 len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC); 1905 return 0;
1891 len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION);
1892
1893 return len;
1894} 1906}
1895 1907
1896static struct ibm_struct thinkpad_acpi_driver_data = { 1908static struct ibm_struct thinkpad_acpi_driver_data = {
@@ -2186,7 +2198,8 @@ static int hotkey_mask_set(u32 mask)
2186 fwmask, hotkey_acpi_mask); 2198 fwmask, hotkey_acpi_mask);
2187 } 2199 }
2188 2200
2189 hotkey_mask_warn_incomplete_mask(); 2201 if (tpacpi_lifecycle != TPACPI_LIFE_EXITING)
2202 hotkey_mask_warn_incomplete_mask();
2190 2203
2191 return rc; 2204 return rc;
2192} 2205}
@@ -3182,6 +3195,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3182 int res, i; 3195 int res, i;
3183 int status; 3196 int status;
3184 int hkeyv; 3197 int hkeyv;
3198 bool radiosw_state = false;
3199 bool tabletsw_state = false;
3185 3200
3186 unsigned long quirks; 3201 unsigned long quirks;
3187 3202
@@ -3287,6 +3302,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3287#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3302#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3288 if (dbg_wlswemul) { 3303 if (dbg_wlswemul) {
3289 tp_features.hotkey_wlsw = 1; 3304 tp_features.hotkey_wlsw = 1;
3305 radiosw_state = !!tpacpi_wlsw_emulstate;
3290 printk(TPACPI_INFO 3306 printk(TPACPI_INFO
3291 "radio switch emulation enabled\n"); 3307 "radio switch emulation enabled\n");
3292 } else 3308 } else
@@ -3294,6 +3310,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3294 /* Not all thinkpads have a hardware radio switch */ 3310 /* Not all thinkpads have a hardware radio switch */
3295 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { 3311 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
3296 tp_features.hotkey_wlsw = 1; 3312 tp_features.hotkey_wlsw = 1;
3313 radiosw_state = !!status;
3297 printk(TPACPI_INFO 3314 printk(TPACPI_INFO
3298 "radio switch found; radios are %s\n", 3315 "radio switch found; radios are %s\n",
3299 enabled(status, 0)); 3316 enabled(status, 0));
@@ -3305,11 +3322,11 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3305 /* For X41t, X60t, X61t Tablets... */ 3322 /* For X41t, X60t, X61t Tablets... */
3306 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { 3323 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
3307 tp_features.hotkey_tablet = 1; 3324 tp_features.hotkey_tablet = 1;
3325 tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK);
3308 printk(TPACPI_INFO 3326 printk(TPACPI_INFO
3309 "possible tablet mode switch found; " 3327 "possible tablet mode switch found; "
3310 "ThinkPad in %s mode\n", 3328 "ThinkPad in %s mode\n",
3311 (status & TP_HOTKEY_TABLET_MASK)? 3329 (tabletsw_state) ? "tablet" : "laptop");
3312 "tablet" : "laptop");
3313 res = add_to_attr_set(hotkey_dev_attributes, 3330 res = add_to_attr_set(hotkey_dev_attributes,
3314 &dev_attr_hotkey_tablet_mode.attr); 3331 &dev_attr_hotkey_tablet_mode.attr);
3315 } 3332 }
@@ -3344,16 +3361,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3344 TPACPI_HOTKEY_MAP_SIZE); 3361 TPACPI_HOTKEY_MAP_SIZE);
3345 } 3362 }
3346 3363
3347 set_bit(EV_KEY, tpacpi_inputdev->evbit); 3364 input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
3348 set_bit(EV_MSC, tpacpi_inputdev->evbit);
3349 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
3350 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; 3365 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
3351 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; 3366 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
3352 tpacpi_inputdev->keycode = hotkey_keycode_map; 3367 tpacpi_inputdev->keycode = hotkey_keycode_map;
3353 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { 3368 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
3354 if (hotkey_keycode_map[i] != KEY_RESERVED) { 3369 if (hotkey_keycode_map[i] != KEY_RESERVED) {
3355 set_bit(hotkey_keycode_map[i], 3370 input_set_capability(tpacpi_inputdev, EV_KEY,
3356 tpacpi_inputdev->keybit); 3371 hotkey_keycode_map[i]);
3357 } else { 3372 } else {
3358 if (i < sizeof(hotkey_reserved_mask)*8) 3373 if (i < sizeof(hotkey_reserved_mask)*8)
3359 hotkey_reserved_mask |= 1 << i; 3374 hotkey_reserved_mask |= 1 << i;
@@ -3361,12 +3376,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3361 } 3376 }
3362 3377
3363 if (tp_features.hotkey_wlsw) { 3378 if (tp_features.hotkey_wlsw) {
3364 set_bit(EV_SW, tpacpi_inputdev->evbit); 3379 input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL);
3365 set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); 3380 input_report_switch(tpacpi_inputdev,
3381 SW_RFKILL_ALL, radiosw_state);
3366 } 3382 }
3367 if (tp_features.hotkey_tablet) { 3383 if (tp_features.hotkey_tablet) {
3368 set_bit(EV_SW, tpacpi_inputdev->evbit); 3384 input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE);
3369 set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); 3385 input_report_switch(tpacpi_inputdev,
3386 SW_TABLET_MODE, tabletsw_state);
3370 } 3387 }
3371 3388
3372 /* Do not issue duplicate brightness change events to 3389 /* Do not issue duplicate brightness change events to
@@ -3433,8 +3450,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3433 tpacpi_inputdev->close = &hotkey_inputdev_close; 3450 tpacpi_inputdev->close = &hotkey_inputdev_close;
3434 3451
3435 hotkey_poll_setup_safe(true); 3452 hotkey_poll_setup_safe(true);
3436 tpacpi_send_radiosw_update();
3437 tpacpi_input_send_tabletsw();
3438 3453
3439 return 0; 3454 return 0;
3440 3455
@@ -3542,49 +3557,57 @@ static bool hotkey_notify_usrevent(const u32 hkey,
3542 } 3557 }
3543} 3558}
3544 3559
3560static void thermal_dump_all_sensors(void);
3561
3545static bool hotkey_notify_thermal(const u32 hkey, 3562static bool hotkey_notify_thermal(const u32 hkey,
3546 bool *send_acpi_ev, 3563 bool *send_acpi_ev,
3547 bool *ignore_acpi_ev) 3564 bool *ignore_acpi_ev)
3548{ 3565{
3566 bool known = true;
3567
3549 /* 0x6000-0x6FFF: thermal alarms */ 3568 /* 0x6000-0x6FFF: thermal alarms */
3550 *send_acpi_ev = true; 3569 *send_acpi_ev = true;
3551 *ignore_acpi_ev = false; 3570 *ignore_acpi_ev = false;
3552 3571
3553 switch (hkey) { 3572 switch (hkey) {
3573 case TP_HKEY_EV_THM_TABLE_CHANGED:
3574 printk(TPACPI_INFO
3575 "EC reports that Thermal Table has changed\n");
3576 /* recommended action: do nothing, we don't have
3577 * Lenovo ATM information */
3578 return true;
3554 case TP_HKEY_EV_ALARM_BAT_HOT: 3579 case TP_HKEY_EV_ALARM_BAT_HOT:
3555 printk(TPACPI_CRIT 3580 printk(TPACPI_CRIT
3556 "THERMAL ALARM: battery is too hot!\n"); 3581 "THERMAL ALARM: battery is too hot!\n");
3557 /* recommended action: warn user through gui */ 3582 /* recommended action: warn user through gui */
3558 return true; 3583 break;
3559 case TP_HKEY_EV_ALARM_BAT_XHOT: 3584 case TP_HKEY_EV_ALARM_BAT_XHOT:
3560 printk(TPACPI_ALERT 3585 printk(TPACPI_ALERT
3561 "THERMAL EMERGENCY: battery is extremely hot!\n"); 3586 "THERMAL EMERGENCY: battery is extremely hot!\n");
3562 /* recommended action: immediate sleep/hibernate */ 3587 /* recommended action: immediate sleep/hibernate */
3563 return true; 3588 break;
3564 case TP_HKEY_EV_ALARM_SENSOR_HOT: 3589 case TP_HKEY_EV_ALARM_SENSOR_HOT:
3565 printk(TPACPI_CRIT 3590 printk(TPACPI_CRIT
3566 "THERMAL ALARM: " 3591 "THERMAL ALARM: "
3567 "a sensor reports something is too hot!\n"); 3592 "a sensor reports something is too hot!\n");
3568 /* recommended action: warn user through gui, that */ 3593 /* recommended action: warn user through gui, that */
3569 /* some internal component is too hot */ 3594 /* some internal component is too hot */
3570 return true; 3595 break;
3571 case TP_HKEY_EV_ALARM_SENSOR_XHOT: 3596 case TP_HKEY_EV_ALARM_SENSOR_XHOT:
3572 printk(TPACPI_ALERT 3597 printk(TPACPI_ALERT
3573 "THERMAL EMERGENCY: " 3598 "THERMAL EMERGENCY: "
3574 "a sensor reports something is extremely hot!\n"); 3599 "a sensor reports something is extremely hot!\n");
3575 /* recommended action: immediate sleep/hibernate */ 3600 /* recommended action: immediate sleep/hibernate */
3576 return true; 3601 break;
3577 case TP_HKEY_EV_THM_TABLE_CHANGED:
3578 printk(TPACPI_INFO
3579 "EC reports that Thermal Table has changed\n");
3580 /* recommended action: do nothing, we don't have
3581 * Lenovo ATM information */
3582 return true;
3583 default: 3602 default:
3584 printk(TPACPI_ALERT 3603 printk(TPACPI_ALERT
3585 "THERMAL ALERT: unknown thermal alarm received\n"); 3604 "THERMAL ALERT: unknown thermal alarm received\n");
3586 return false; 3605 known = false;
3587 } 3606 }
3607
3608 thermal_dump_all_sensors();
3609
3610 return known;
3588} 3611}
3589 3612
3590static void hotkey_notify(struct ibm_struct *ibm, u32 event) 3613static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -3727,14 +3750,13 @@ static void hotkey_resume(void)
3727} 3750}
3728 3751
3729/* procfs -------------------------------------------------------------- */ 3752/* procfs -------------------------------------------------------------- */
3730static int hotkey_read(char *p) 3753static int hotkey_read(struct seq_file *m)
3731{ 3754{
3732 int res, status; 3755 int res, status;
3733 int len = 0;
3734 3756
3735 if (!tp_features.hotkey) { 3757 if (!tp_features.hotkey) {
3736 len += sprintf(p + len, "status:\t\tnot supported\n"); 3758 seq_printf(m, "status:\t\tnot supported\n");
3737 return len; 3759 return 0;
3738 } 3760 }
3739 3761
3740 if (mutex_lock_killable(&hotkey_mutex)) 3762 if (mutex_lock_killable(&hotkey_mutex))
@@ -3746,17 +3768,16 @@ static int hotkey_read(char *p)
3746 if (res) 3768 if (res)
3747 return res; 3769 return res;
3748 3770
3749 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); 3771 seq_printf(m, "status:\t\t%s\n", enabled(status, 0));
3750 if (hotkey_all_mask) { 3772 if (hotkey_all_mask) {
3751 len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_user_mask); 3773 seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask);
3752 len += sprintf(p + len, 3774 seq_printf(m, "commands:\tenable, disable, reset, <mask>\n");
3753 "commands:\tenable, disable, reset, <mask>\n");
3754 } else { 3775 } else {
3755 len += sprintf(p + len, "mask:\t\tnot supported\n"); 3776 seq_printf(m, "mask:\t\tnot supported\n");
3756 len += sprintf(p + len, "commands:\tenable, disable, reset\n"); 3777 seq_printf(m, "commands:\tenable, disable, reset\n");
3757 } 3778 }
3758 3779
3759 return len; 3780 return 0;
3760} 3781}
3761 3782
3762static void hotkey_enabledisable_warn(bool enable) 3783static void hotkey_enabledisable_warn(bool enable)
@@ -3863,15 +3884,6 @@ enum {
3863 3884
3864#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" 3885#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw"
3865 3886
3866static void bluetooth_suspend(pm_message_t state)
3867{
3868 /* Try to make sure radio will resume powered off */
3869 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
3870 TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
3871 vdbg_printk(TPACPI_DBG_RFKILL,
3872 "bluetooth power down on resume request failed\n");
3873}
3874
3875static int bluetooth_get_status(void) 3887static int bluetooth_get_status(void)
3876{ 3888{
3877 int status; 3889 int status;
@@ -3905,10 +3917,9 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state)
3905#endif 3917#endif
3906 3918
3907 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ 3919 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
3920 status = TP_ACPI_BLUETOOTH_RESUMECTRL;
3908 if (state == TPACPI_RFK_RADIO_ON) 3921 if (state == TPACPI_RFK_RADIO_ON)
3909 status = TP_ACPI_BLUETOOTH_RADIOSSW; 3922 status |= TP_ACPI_BLUETOOTH_RADIOSSW;
3910 else
3911 status = 0;
3912 3923
3913 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 3924 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
3914 return -EIO; 3925 return -EIO;
@@ -4032,9 +4043,9 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
4032} 4043}
4033 4044
4034/* procfs -------------------------------------------------------------- */ 4045/* procfs -------------------------------------------------------------- */
4035static int bluetooth_read(char *p) 4046static int bluetooth_read(struct seq_file *m)
4036{ 4047{
4037 return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p); 4048 return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, m);
4038} 4049}
4039 4050
4040static int bluetooth_write(char *buf) 4051static int bluetooth_write(char *buf)
@@ -4047,7 +4058,6 @@ static struct ibm_struct bluetooth_driver_data = {
4047 .read = bluetooth_read, 4058 .read = bluetooth_read,
4048 .write = bluetooth_write, 4059 .write = bluetooth_write,
4049 .exit = bluetooth_exit, 4060 .exit = bluetooth_exit,
4050 .suspend = bluetooth_suspend,
4051 .shutdown = bluetooth_shutdown, 4061 .shutdown = bluetooth_shutdown,
4052}; 4062};
4053 4063
@@ -4065,15 +4075,6 @@ enum {
4065 4075
4066#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" 4076#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
4067 4077
4068static void wan_suspend(pm_message_t state)
4069{
4070 /* Try to make sure radio will resume powered off */
4071 if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
4072 TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
4073 vdbg_printk(TPACPI_DBG_RFKILL,
4074 "WWAN power down on resume request failed\n");
4075}
4076
4077static int wan_get_status(void) 4078static int wan_get_status(void)
4078{ 4079{
4079 int status; 4080 int status;
@@ -4106,11 +4107,10 @@ static int wan_set_status(enum tpacpi_rfkill_state state)
4106 } 4107 }
4107#endif 4108#endif
4108 4109
4109 /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */ 4110 /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
4111 status = TP_ACPI_WANCARD_RESUMECTRL;
4110 if (state == TPACPI_RFK_RADIO_ON) 4112 if (state == TPACPI_RFK_RADIO_ON)
4111 status = TP_ACPI_WANCARD_RADIOSSW; 4113 status |= TP_ACPI_WANCARD_RADIOSSW;
4112 else
4113 status = 0;
4114 4114
4115 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 4115 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
4116 return -EIO; 4116 return -EIO;
@@ -4233,9 +4233,9 @@ static int __init wan_init(struct ibm_init_struct *iibm)
4233} 4233}
4234 4234
4235/* procfs -------------------------------------------------------------- */ 4235/* procfs -------------------------------------------------------------- */
4236static int wan_read(char *p) 4236static int wan_read(struct seq_file *m)
4237{ 4237{
4238 return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p); 4238 return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, m);
4239} 4239}
4240 4240
4241static int wan_write(char *buf) 4241static int wan_write(char *buf)
@@ -4248,7 +4248,6 @@ static struct ibm_struct wan_driver_data = {
4248 .read = wan_read, 4248 .read = wan_read,
4249 .write = wan_write, 4249 .write = wan_write,
4250 .exit = wan_exit, 4250 .exit = wan_exit,
4251 .suspend = wan_suspend,
4252 .shutdown = wan_shutdown, 4251 .shutdown = wan_shutdown,
4253}; 4252};
4254 4253
@@ -4611,14 +4610,13 @@ static int video_expand_toggle(void)
4611 /* not reached */ 4610 /* not reached */
4612} 4611}
4613 4612
4614static int video_read(char *p) 4613static int video_read(struct seq_file *m)
4615{ 4614{
4616 int status, autosw; 4615 int status, autosw;
4617 int len = 0;
4618 4616
4619 if (video_supported == TPACPI_VIDEO_NONE) { 4617 if (video_supported == TPACPI_VIDEO_NONE) {
4620 len += sprintf(p + len, "status:\t\tnot supported\n"); 4618 seq_printf(m, "status:\t\tnot supported\n");
4621 return len; 4619 return 0;
4622 } 4620 }
4623 4621
4624 status = video_outputsw_get(); 4622 status = video_outputsw_get();
@@ -4629,20 +4627,20 @@ static int video_read(char *p)
4629 if (autosw < 0) 4627 if (autosw < 0)
4630 return autosw; 4628 return autosw;
4631 4629
4632 len += sprintf(p + len, "status:\t\tsupported\n"); 4630 seq_printf(m, "status:\t\tsupported\n");
4633 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0)); 4631 seq_printf(m, "lcd:\t\t%s\n", enabled(status, 0));
4634 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1)); 4632 seq_printf(m, "crt:\t\t%s\n", enabled(status, 1));
4635 if (video_supported == TPACPI_VIDEO_NEW) 4633 if (video_supported == TPACPI_VIDEO_NEW)
4636 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3)); 4634 seq_printf(m, "dvi:\t\t%s\n", enabled(status, 3));
4637 len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0)); 4635 seq_printf(m, "auto:\t\t%s\n", enabled(autosw, 0));
4638 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n"); 4636 seq_printf(m, "commands:\tlcd_enable, lcd_disable\n");
4639 len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n"); 4637 seq_printf(m, "commands:\tcrt_enable, crt_disable\n");
4640 if (video_supported == TPACPI_VIDEO_NEW) 4638 if (video_supported == TPACPI_VIDEO_NEW)
4641 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n"); 4639 seq_printf(m, "commands:\tdvi_enable, dvi_disable\n");
4642 len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n"); 4640 seq_printf(m, "commands:\tauto_enable, auto_disable\n");
4643 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n"); 4641 seq_printf(m, "commands:\tvideo_switch, expand_toggle\n");
4644 4642
4645 return len; 4643 return 0;
4646} 4644}
4647 4645
4648static int video_write(char *buf) 4646static int video_write(char *buf)
@@ -4834,25 +4832,24 @@ static void light_exit(void)
4834 flush_workqueue(tpacpi_wq); 4832 flush_workqueue(tpacpi_wq);
4835} 4833}
4836 4834
4837static int light_read(char *p) 4835static int light_read(struct seq_file *m)
4838{ 4836{
4839 int len = 0;
4840 int status; 4837 int status;
4841 4838
4842 if (!tp_features.light) { 4839 if (!tp_features.light) {
4843 len += sprintf(p + len, "status:\t\tnot supported\n"); 4840 seq_printf(m, "status:\t\tnot supported\n");
4844 } else if (!tp_features.light_status) { 4841 } else if (!tp_features.light_status) {
4845 len += sprintf(p + len, "status:\t\tunknown\n"); 4842 seq_printf(m, "status:\t\tunknown\n");
4846 len += sprintf(p + len, "commands:\ton, off\n"); 4843 seq_printf(m, "commands:\ton, off\n");
4847 } else { 4844 } else {
4848 status = light_get_status(); 4845 status = light_get_status();
4849 if (status < 0) 4846 if (status < 0)
4850 return status; 4847 return status;
4851 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); 4848 seq_printf(m, "status:\t\t%s\n", onoff(status, 0));
4852 len += sprintf(p + len, "commands:\ton, off\n"); 4849 seq_printf(m, "commands:\ton, off\n");
4853 } 4850 }
4854 4851
4855 return len; 4852 return 0;
4856} 4853}
4857 4854
4858static int light_write(char *buf) 4855static int light_write(char *buf)
@@ -4930,20 +4927,18 @@ static void cmos_exit(void)
4930 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command); 4927 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
4931} 4928}
4932 4929
4933static int cmos_read(char *p) 4930static int cmos_read(struct seq_file *m)
4934{ 4931{
4935 int len = 0;
4936
4937 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, 4932 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
4938 R30, R31, T20-22, X20-21 */ 4933 R30, R31, T20-22, X20-21 */
4939 if (!cmos_handle) 4934 if (!cmos_handle)
4940 len += sprintf(p + len, "status:\t\tnot supported\n"); 4935 seq_printf(m, "status:\t\tnot supported\n");
4941 else { 4936 else {
4942 len += sprintf(p + len, "status:\t\tsupported\n"); 4937 seq_printf(m, "status:\t\tsupported\n");
4943 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n"); 4938 seq_printf(m, "commands:\t<cmd> (<cmd> is 0-21)\n");
4944 } 4939 }
4945 4940
4946 return len; 4941 return 0;
4947} 4942}
4948 4943
4949static int cmos_write(char *buf) 4944static int cmos_write(char *buf)
@@ -5318,15 +5313,13 @@ static int __init led_init(struct ibm_init_struct *iibm)
5318 ((s) == TPACPI_LED_OFF ? "off" : \ 5313 ((s) == TPACPI_LED_OFF ? "off" : \
5319 ((s) == TPACPI_LED_ON ? "on" : "blinking")) 5314 ((s) == TPACPI_LED_ON ? "on" : "blinking"))
5320 5315
5321static int led_read(char *p) 5316static int led_read(struct seq_file *m)
5322{ 5317{
5323 int len = 0;
5324
5325 if (!led_supported) { 5318 if (!led_supported) {
5326 len += sprintf(p + len, "status:\t\tnot supported\n"); 5319 seq_printf(m, "status:\t\tnot supported\n");
5327 return len; 5320 return 0;
5328 } 5321 }
5329 len += sprintf(p + len, "status:\t\tsupported\n"); 5322 seq_printf(m, "status:\t\tsupported\n");
5330 5323
5331 if (led_supported == TPACPI_LED_570) { 5324 if (led_supported == TPACPI_LED_570) {
5332 /* 570 */ 5325 /* 570 */
@@ -5335,15 +5328,15 @@ static int led_read(char *p)
5335 status = led_get_status(i); 5328 status = led_get_status(i);
5336 if (status < 0) 5329 if (status < 0)
5337 return -EIO; 5330 return -EIO;
5338 len += sprintf(p + len, "%d:\t\t%s\n", 5331 seq_printf(m, "%d:\t\t%s\n",
5339 i, str_led_status(status)); 5332 i, str_led_status(status));
5340 } 5333 }
5341 } 5334 }
5342 5335
5343 len += sprintf(p + len, "commands:\t" 5336 seq_printf(m, "commands:\t"
5344 "<led> on, <led> off, <led> blink (<led> is 0-15)\n"); 5337 "<led> on, <led> off, <led> blink (<led> is 0-15)\n");
5345 5338
5346 return len; 5339 return 0;
5347} 5340}
5348 5341
5349static int led_write(char *buf) 5342static int led_write(char *buf)
@@ -5416,18 +5409,16 @@ static int __init beep_init(struct ibm_init_struct *iibm)
5416 return (beep_handle)? 0 : 1; 5409 return (beep_handle)? 0 : 1;
5417} 5410}
5418 5411
5419static int beep_read(char *p) 5412static int beep_read(struct seq_file *m)
5420{ 5413{
5421 int len = 0;
5422
5423 if (!beep_handle) 5414 if (!beep_handle)
5424 len += sprintf(p + len, "status:\t\tnot supported\n"); 5415 seq_printf(m, "status:\t\tnot supported\n");
5425 else { 5416 else {
5426 len += sprintf(p + len, "status:\t\tsupported\n"); 5417 seq_printf(m, "status:\t\tsupported\n");
5427 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n"); 5418 seq_printf(m, "commands:\t<cmd> (<cmd> is 0-17)\n");
5428 } 5419 }
5429 5420
5430 return len; 5421 return 0;
5431} 5422}
5432 5423
5433static int beep_write(char *buf) 5424static int beep_write(char *buf)
@@ -5480,8 +5471,11 @@ enum { /* TPACPI_THERMAL_TPEC_* */
5480 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */ 5471 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */
5481 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */ 5472 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */
5482 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */ 5473 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */
5474
5475 TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */
5483}; 5476};
5484 5477
5478
5485#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */ 5479#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
5486struct ibm_thermal_sensors_struct { 5480struct ibm_thermal_sensors_struct {
5487 s32 temp[TPACPI_MAX_THERMAL_SENSORS]; 5481 s32 temp[TPACPI_MAX_THERMAL_SENSORS];
@@ -5571,6 +5565,28 @@ static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
5571 return n; 5565 return n;
5572} 5566}
5573 5567
5568static void thermal_dump_all_sensors(void)
5569{
5570 int n, i;
5571 struct ibm_thermal_sensors_struct t;
5572
5573 n = thermal_get_sensors(&t);
5574 if (n <= 0)
5575 return;
5576
5577 printk(TPACPI_NOTICE
5578 "temperatures (Celsius):");
5579
5580 for (i = 0; i < n; i++) {
5581 if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA)
5582 printk(KERN_CONT " %d", (int)(t.temp[i] / 1000));
5583 else
5584 printk(KERN_CONT " N/A");
5585 }
5586
5587 printk(KERN_CONT "\n");
5588}
5589
5574/* sysfs temp##_input -------------------------------------------------- */ 5590/* sysfs temp##_input -------------------------------------------------- */
5575 5591
5576static ssize_t thermal_temp_input_show(struct device *dev, 5592static ssize_t thermal_temp_input_show(struct device *dev,
@@ -5586,7 +5602,7 @@ static ssize_t thermal_temp_input_show(struct device *dev,
5586 res = thermal_get_sensor(idx, &value); 5602 res = thermal_get_sensor(idx, &value);
5587 if (res) 5603 if (res)
5588 return res; 5604 return res;
5589 if (value == TP_EC_THERMAL_TMP_NA * 1000) 5605 if (value == TPACPI_THERMAL_SENSOR_NA)
5590 return -ENXIO; 5606 return -ENXIO;
5591 5607
5592 return snprintf(buf, PAGE_SIZE, "%d\n", value); 5608 return snprintf(buf, PAGE_SIZE, "%d\n", value);
@@ -5763,9 +5779,8 @@ static void thermal_exit(void)
5763 } 5779 }
5764} 5780}
5765 5781
5766static int thermal_read(char *p) 5782static int thermal_read(struct seq_file *m)
5767{ 5783{
5768 int len = 0;
5769 int n, i; 5784 int n, i;
5770 struct ibm_thermal_sensors_struct t; 5785 struct ibm_thermal_sensors_struct t;
5771 5786
@@ -5773,16 +5788,16 @@ static int thermal_read(char *p)
5773 if (unlikely(n < 0)) 5788 if (unlikely(n < 0))
5774 return n; 5789 return n;
5775 5790
5776 len += sprintf(p + len, "temperatures:\t"); 5791 seq_printf(m, "temperatures:\t");
5777 5792
5778 if (n > 0) { 5793 if (n > 0) {
5779 for (i = 0; i < (n - 1); i++) 5794 for (i = 0; i < (n - 1); i++)
5780 len += sprintf(p + len, "%d ", t.temp[i] / 1000); 5795 seq_printf(m, "%d ", t.temp[i] / 1000);
5781 len += sprintf(p + len, "%d\n", t.temp[i] / 1000); 5796 seq_printf(m, "%d\n", t.temp[i] / 1000);
5782 } else 5797 } else
5783 len += sprintf(p + len, "not supported\n"); 5798 seq_printf(m, "not supported\n");
5784 5799
5785 return len; 5800 return 0;
5786} 5801}
5787 5802
5788static struct ibm_struct thermal_driver_data = { 5803static struct ibm_struct thermal_driver_data = {
@@ -5797,39 +5812,38 @@ static struct ibm_struct thermal_driver_data = {
5797 5812
5798static u8 ecdump_regs[256]; 5813static u8 ecdump_regs[256];
5799 5814
5800static int ecdump_read(char *p) 5815static int ecdump_read(struct seq_file *m)
5801{ 5816{
5802 int len = 0;
5803 int i, j; 5817 int i, j;
5804 u8 v; 5818 u8 v;
5805 5819
5806 len += sprintf(p + len, "EC " 5820 seq_printf(m, "EC "
5807 " +00 +01 +02 +03 +04 +05 +06 +07" 5821 " +00 +01 +02 +03 +04 +05 +06 +07"
5808 " +08 +09 +0a +0b +0c +0d +0e +0f\n"); 5822 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
5809 for (i = 0; i < 256; i += 16) { 5823 for (i = 0; i < 256; i += 16) {
5810 len += sprintf(p + len, "EC 0x%02x:", i); 5824 seq_printf(m, "EC 0x%02x:", i);
5811 for (j = 0; j < 16; j++) { 5825 for (j = 0; j < 16; j++) {
5812 if (!acpi_ec_read(i + j, &v)) 5826 if (!acpi_ec_read(i + j, &v))
5813 break; 5827 break;
5814 if (v != ecdump_regs[i + j]) 5828 if (v != ecdump_regs[i + j])
5815 len += sprintf(p + len, " *%02x", v); 5829 seq_printf(m, " *%02x", v);
5816 else 5830 else
5817 len += sprintf(p + len, " %02x", v); 5831 seq_printf(m, " %02x", v);
5818 ecdump_regs[i + j] = v; 5832 ecdump_regs[i + j] = v;
5819 } 5833 }
5820 len += sprintf(p + len, "\n"); 5834 seq_putc(m, '\n');
5821 if (j != 16) 5835 if (j != 16)
5822 break; 5836 break;
5823 } 5837 }
5824 5838
5825 /* These are way too dangerous to advertise openly... */ 5839 /* These are way too dangerous to advertise openly... */
5826#if 0 5840#if 0
5827 len += sprintf(p + len, "commands:\t0x<offset> 0x<value>" 5841 seq_printf(m, "commands:\t0x<offset> 0x<value>"
5828 " (<offset> is 00-ff, <value> is 00-ff)\n"); 5842 " (<offset> is 00-ff, <value> is 00-ff)\n");
5829 len += sprintf(p + len, "commands:\t0x<offset> <value> " 5843 seq_printf(m, "commands:\t0x<offset> <value> "
5830 " (<offset> is 00-ff, <value> is 0-255)\n"); 5844 " (<offset> is 00-ff, <value> is 0-255)\n");
5831#endif 5845#endif
5832 return len; 5846 return 0;
5833} 5847}
5834 5848
5835static int ecdump_write(char *buf) 5849static int ecdump_write(char *buf)
@@ -6092,6 +6106,12 @@ static int brightness_get(struct backlight_device *bd)
6092 return status & TP_EC_BACKLIGHT_LVLMSK; 6106 return status & TP_EC_BACKLIGHT_LVLMSK;
6093} 6107}
6094 6108
6109static void tpacpi_brightness_notify_change(void)
6110{
6111 backlight_force_update(ibm_backlight_device,
6112 BACKLIGHT_UPDATE_HOTKEY);
6113}
6114
6095static struct backlight_ops ibm_backlight_data = { 6115static struct backlight_ops ibm_backlight_data = {
6096 .get_brightness = brightness_get, 6116 .get_brightness = brightness_get,
6097 .update_status = brightness_update_status, 6117 .update_status = brightness_update_status,
@@ -6120,8 +6140,8 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6120 6140
6121 /* Models with Intel Extreme Graphics 2 */ 6141 /* Models with Intel Extreme Graphics 2 */
6122 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), 6142 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
6123 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), 6143 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6124 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), 6144 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6125 6145
6126 /* Models with Intel GMA900 */ 6146 /* Models with Intel GMA900 */
6127 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ 6147 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */
@@ -6246,6 +6266,12 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6246 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; 6266 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6247 backlight_update_status(ibm_backlight_device); 6267 backlight_update_status(ibm_backlight_device);
6248 6268
6269 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
6270 "brightness: registering brightness hotkeys "
6271 "as change notification\n");
6272 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
6273 | TP_ACPI_HKEY_BRGHTUP_MASK
6274 | TP_ACPI_HKEY_BRGHTDWN_MASK);;
6249 return 0; 6275 return 0;
6250} 6276}
6251 6277
@@ -6270,23 +6296,22 @@ static void brightness_exit(void)
6270 tpacpi_brightness_checkpoint_nvram(); 6296 tpacpi_brightness_checkpoint_nvram();
6271} 6297}
6272 6298
6273static int brightness_read(char *p) 6299static int brightness_read(struct seq_file *m)
6274{ 6300{
6275 int len = 0;
6276 int level; 6301 int level;
6277 6302
6278 level = brightness_get(NULL); 6303 level = brightness_get(NULL);
6279 if (level < 0) { 6304 if (level < 0) {
6280 len += sprintf(p + len, "level:\t\tunreadable\n"); 6305 seq_printf(m, "level:\t\tunreadable\n");
6281 } else { 6306 } else {
6282 len += sprintf(p + len, "level:\t\t%d\n", level); 6307 seq_printf(m, "level:\t\t%d\n", level);
6283 len += sprintf(p + len, "commands:\tup, down\n"); 6308 seq_printf(m, "commands:\tup, down\n");
6284 len += sprintf(p + len, "commands:\tlevel <level>" 6309 seq_printf(m, "commands:\tlevel <level>"
6285 " (<level> is 0-%d)\n", 6310 " (<level> is 0-%d)\n",
6286 (tp_features.bright_16levels) ? 15 : 7); 6311 (tp_features.bright_16levels) ? 15 : 7);
6287 } 6312 }
6288 6313
6289 return len; 6314 return 0;
6290} 6315}
6291 6316
6292static int brightness_write(char *buf) 6317static int brightness_write(char *buf)
@@ -6322,6 +6347,9 @@ static int brightness_write(char *buf)
6322 * Doing it this way makes the syscall restartable in case of EINTR 6347 * Doing it this way makes the syscall restartable in case of EINTR
6323 */ 6348 */
6324 rc = brightness_set(level); 6349 rc = brightness_set(level);
6350 if (!rc && ibm_backlight_device)
6351 backlight_force_update(ibm_backlight_device,
6352 BACKLIGHT_UPDATE_SYSFS);
6325 return (rc == -EINTR)? -ERESTARTSYS : rc; 6353 return (rc == -EINTR)? -ERESTARTSYS : rc;
6326} 6354}
6327 6355
@@ -6338,99 +6366,654 @@ static struct ibm_struct brightness_driver_data = {
6338 * Volume subdriver 6366 * Volume subdriver
6339 */ 6367 */
6340 6368
6341static int volume_offset = 0x30; 6369/*
6370 * IBM ThinkPads have a simple volume controller with MUTE gating.
6371 * Very early Lenovo ThinkPads follow the IBM ThinkPad spec.
6372 *
6373 * Since the *61 series (and probably also the later *60 series), Lenovo
6374 * ThinkPads only implement the MUTE gate.
6375 *
6376 * EC register 0x30
6377 * Bit 6: MUTE (1 mutes sound)
6378 * Bit 3-0: Volume
6379 * Other bits should be zero as far as we know.
6380 *
6381 * This is also stored in CMOS NVRAM, byte 0x60, bit 6 (MUTE), and
6382 * bits 3-0 (volume). Other bits in NVRAM may have other functions,
6383 * such as bit 7 which is used to detect repeated presses of MUTE,
6384 * and we leave them unchanged.
6385 */
6386
6387#define TPACPI_ALSA_DRVNAME "ThinkPad EC"
6388#define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
6389#define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME
6390
6391static int alsa_index = SNDRV_DEFAULT_IDX1;
6392static char *alsa_id = "ThinkPadEC";
6393static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
6394
6395struct tpacpi_alsa_data {
6396 struct snd_card *card;
6397 struct snd_ctl_elem_id *ctl_mute_id;
6398 struct snd_ctl_elem_id *ctl_vol_id;
6399};
6400
6401static struct snd_card *alsa_card;
6402
6403enum {
6404 TP_EC_AUDIO = 0x30,
6405
6406 /* TP_EC_AUDIO bits */
6407 TP_EC_AUDIO_MUTESW = 6,
6408
6409 /* TP_EC_AUDIO bitmasks */
6410 TP_EC_AUDIO_LVL_MSK = 0x0F,
6411 TP_EC_AUDIO_MUTESW_MSK = (1 << TP_EC_AUDIO_MUTESW),
6412
6413 /* Maximum volume */
6414 TP_EC_VOLUME_MAX = 14,
6415};
6416
6417enum tpacpi_volume_access_mode {
6418 TPACPI_VOL_MODE_AUTO = 0, /* Not implemented yet */
6419 TPACPI_VOL_MODE_EC, /* Pure EC control */
6420 TPACPI_VOL_MODE_UCMS_STEP, /* UCMS step-based control: N/A */
6421 TPACPI_VOL_MODE_ECNVRAM, /* EC control w/ NVRAM store */
6422 TPACPI_VOL_MODE_MAX
6423};
6424
6425enum tpacpi_volume_capabilities {
6426 TPACPI_VOL_CAP_AUTO = 0, /* Use white/blacklist */
6427 TPACPI_VOL_CAP_VOLMUTE, /* Output vol and mute */
6428 TPACPI_VOL_CAP_MUTEONLY, /* Output mute only */
6429 TPACPI_VOL_CAP_MAX
6430};
6431
6432static enum tpacpi_volume_access_mode volume_mode =
6433 TPACPI_VOL_MODE_MAX;
6434
6435static enum tpacpi_volume_capabilities volume_capabilities;
6436static int volume_control_allowed;
6342 6437
6343static int volume_read(char *p) 6438/*
6439 * Used to syncronize writers to TP_EC_AUDIO and
6440 * TP_NVRAM_ADDR_MIXER, as we need to do read-modify-write
6441 */
6442static struct mutex volume_mutex;
6443
6444static void tpacpi_volume_checkpoint_nvram(void)
6344{ 6445{
6345 int len = 0; 6446 u8 lec = 0;
6346 u8 level; 6447 u8 b_nvram;
6448 u8 ec_mask;
6449
6450 if (volume_mode != TPACPI_VOL_MODE_ECNVRAM)
6451 return;
6452 if (!volume_control_allowed)
6453 return;
6454
6455 vdbg_printk(TPACPI_DBG_MIXER,
6456 "trying to checkpoint mixer state to NVRAM...\n");
6347 6457
6348 if (!acpi_ec_read(volume_offset, &level)) { 6458 if (tp_features.mixer_no_level_control)
6349 len += sprintf(p + len, "level:\t\tunreadable\n"); 6459 ec_mask = TP_EC_AUDIO_MUTESW_MSK;
6460 else
6461 ec_mask = TP_EC_AUDIO_MUTESW_MSK | TP_EC_AUDIO_LVL_MSK;
6462
6463 if (mutex_lock_killable(&volume_mutex) < 0)
6464 return;
6465
6466 if (unlikely(!acpi_ec_read(TP_EC_AUDIO, &lec)))
6467 goto unlock;
6468 lec &= ec_mask;
6469 b_nvram = nvram_read_byte(TP_NVRAM_ADDR_MIXER);
6470
6471 if (lec != (b_nvram & ec_mask)) {
6472 /* NVRAM needs update */
6473 b_nvram &= ~ec_mask;
6474 b_nvram |= lec;
6475 nvram_write_byte(b_nvram, TP_NVRAM_ADDR_MIXER);
6476 dbg_printk(TPACPI_DBG_MIXER,
6477 "updated NVRAM mixer status to 0x%02x (0x%02x)\n",
6478 (unsigned int) lec, (unsigned int) b_nvram);
6350 } else { 6479 } else {
6351 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf); 6480 vdbg_printk(TPACPI_DBG_MIXER,
6352 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6)); 6481 "NVRAM mixer status already is 0x%02x (0x%02x)\n",
6353 len += sprintf(p + len, "commands:\tup, down, mute\n"); 6482 (unsigned int) lec, (unsigned int) b_nvram);
6354 len += sprintf(p + len, "commands:\tlevel <level>"
6355 " (<level> is 0-15)\n");
6356 } 6483 }
6357 6484
6358 return len; 6485unlock:
6486 mutex_unlock(&volume_mutex);
6359} 6487}
6360 6488
6361static int volume_write(char *buf) 6489static int volume_get_status_ec(u8 *status)
6362{ 6490{
6363 int cmos_cmd, inc, i; 6491 u8 s;
6364 u8 level, mute;
6365 int new_level, new_mute;
6366 char *cmd;
6367 6492
6368 while ((cmd = next_cmd(&buf))) { 6493 if (!acpi_ec_read(TP_EC_AUDIO, &s))
6369 if (!acpi_ec_read(volume_offset, &level)) 6494 return -EIO;
6370 return -EIO;
6371 new_mute = mute = level & 0x40;
6372 new_level = level = level & 0xf;
6373 6495
6374 if (strlencmp(cmd, "up") == 0) { 6496 *status = s;
6375 if (mute)
6376 new_mute = 0;
6377 else
6378 new_level = level == 15 ? 15 : level + 1;
6379 } else if (strlencmp(cmd, "down") == 0) {
6380 if (mute)
6381 new_mute = 0;
6382 else
6383 new_level = level == 0 ? 0 : level - 1;
6384 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
6385 new_level >= 0 && new_level <= 15) {
6386 /* new_level set */
6387 } else if (strlencmp(cmd, "mute") == 0) {
6388 new_mute = 0x40;
6389 } else
6390 return -EINVAL;
6391 6497
6392 if (new_level != level) { 6498 dbg_printk(TPACPI_DBG_MIXER, "status 0x%02x\n", s);
6393 /* mute doesn't change */
6394 6499
6395 cmos_cmd = (new_level > level) ? 6500 return 0;
6396 TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN; 6501}
6397 inc = new_level > level ? 1 : -1;
6398 6502
6399 if (mute && (issue_thinkpad_cmos_command(cmos_cmd) || 6503static int volume_get_status(u8 *status)
6400 !acpi_ec_write(volume_offset, level))) 6504{
6401 return -EIO; 6505 return volume_get_status_ec(status);
6506}
6402 6507
6403 for (i = level; i != new_level; i += inc) 6508static int volume_set_status_ec(const u8 status)
6404 if (issue_thinkpad_cmos_command(cmos_cmd) || 6509{
6405 !acpi_ec_write(volume_offset, i + inc)) 6510 if (!acpi_ec_write(TP_EC_AUDIO, status))
6406 return -EIO; 6511 return -EIO;
6407 6512
6408 if (mute && 6513 dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status);
6409 (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) || 6514
6410 !acpi_ec_write(volume_offset, new_level + mute))) { 6515 return 0;
6411 return -EIO; 6516}
6412 } 6517
6518static int volume_set_status(const u8 status)
6519{
6520 return volume_set_status_ec(status);
6521}
6522
6523static int volume_set_mute_ec(const bool mute)
6524{
6525 int rc;
6526 u8 s, n;
6527
6528 if (mutex_lock_killable(&volume_mutex) < 0)
6529 return -EINTR;
6530
6531 rc = volume_get_status_ec(&s);
6532 if (rc)
6533 goto unlock;
6534
6535 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
6536 s & ~TP_EC_AUDIO_MUTESW_MSK;
6537
6538 if (n != s)
6539 rc = volume_set_status_ec(n);
6540
6541unlock:
6542 mutex_unlock(&volume_mutex);
6543 return rc;
6544}
6545
6546static int volume_set_mute(const bool mute)
6547{
6548 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
6549 (mute) ? "" : "un");
6550 return volume_set_mute_ec(mute);
6551}
6552
6553static int volume_set_volume_ec(const u8 vol)
6554{
6555 int rc;
6556 u8 s, n;
6557
6558 if (vol > TP_EC_VOLUME_MAX)
6559 return -EINVAL;
6560
6561 if (mutex_lock_killable(&volume_mutex) < 0)
6562 return -EINTR;
6563
6564 rc = volume_get_status_ec(&s);
6565 if (rc)
6566 goto unlock;
6567
6568 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
6569
6570 if (n != s)
6571 rc = volume_set_status_ec(n);
6572
6573unlock:
6574 mutex_unlock(&volume_mutex);
6575 return rc;
6576}
6577
6578static int volume_set_volume(const u8 vol)
6579{
6580 dbg_printk(TPACPI_DBG_MIXER,
6581 "trying to set volume level to %hu\n", vol);
6582 return volume_set_volume_ec(vol);
6583}
6584
6585static void volume_alsa_notify_change(void)
6586{
6587 struct tpacpi_alsa_data *d;
6588
6589 if (alsa_card && alsa_card->private_data) {
6590 d = alsa_card->private_data;
6591 if (d->ctl_mute_id)
6592 snd_ctl_notify(alsa_card,
6593 SNDRV_CTL_EVENT_MASK_VALUE,
6594 d->ctl_mute_id);
6595 if (d->ctl_vol_id)
6596 snd_ctl_notify(alsa_card,
6597 SNDRV_CTL_EVENT_MASK_VALUE,
6598 d->ctl_vol_id);
6599 }
6600}
6601
6602static int volume_alsa_vol_info(struct snd_kcontrol *kcontrol,
6603 struct snd_ctl_elem_info *uinfo)
6604{
6605 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
6606 uinfo->count = 1;
6607 uinfo->value.integer.min = 0;
6608 uinfo->value.integer.max = TP_EC_VOLUME_MAX;
6609 return 0;
6610}
6611
6612static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
6613 struct snd_ctl_elem_value *ucontrol)
6614{
6615 u8 s;
6616 int rc;
6617
6618 rc = volume_get_status(&s);
6619 if (rc < 0)
6620 return rc;
6621
6622 ucontrol->value.integer.value[0] = s & TP_EC_AUDIO_LVL_MSK;
6623 return 0;
6624}
6625
6626static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
6627 struct snd_ctl_elem_value *ucontrol)
6628{
6629 return volume_set_volume(ucontrol->value.integer.value[0]);
6630}
6631
6632#define volume_alsa_mute_info snd_ctl_boolean_mono_info
6633
6634static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
6635 struct snd_ctl_elem_value *ucontrol)
6636{
6637 u8 s;
6638 int rc;
6639
6640 rc = volume_get_status(&s);
6641 if (rc < 0)
6642 return rc;
6643
6644 ucontrol->value.integer.value[0] =
6645 (s & TP_EC_AUDIO_MUTESW_MSK) ? 0 : 1;
6646 return 0;
6647}
6648
6649static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
6650 struct snd_ctl_elem_value *ucontrol)
6651{
6652 return volume_set_mute(!ucontrol->value.integer.value[0]);
6653}
6654
6655static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
6656 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6657 .name = "Console Playback Volume",
6658 .index = 0,
6659 .access = SNDRV_CTL_ELEM_ACCESS_READ,
6660 .info = volume_alsa_vol_info,
6661 .get = volume_alsa_vol_get,
6662};
6663
6664static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
6665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6666 .name = "Console Playback Switch",
6667 .index = 0,
6668 .access = SNDRV_CTL_ELEM_ACCESS_READ,
6669 .info = volume_alsa_mute_info,
6670 .get = volume_alsa_mute_get,
6671};
6672
6673static void volume_suspend(pm_message_t state)
6674{
6675 tpacpi_volume_checkpoint_nvram();
6676}
6677
6678static void volume_resume(void)
6679{
6680 volume_alsa_notify_change();
6681}
6682
6683static void volume_shutdown(void)
6684{
6685 tpacpi_volume_checkpoint_nvram();
6686}
6687
6688static void volume_exit(void)
6689{
6690 if (alsa_card) {
6691 snd_card_free(alsa_card);
6692 alsa_card = NULL;
6693 }
6694
6695 tpacpi_volume_checkpoint_nvram();
6696}
6697
6698static int __init volume_create_alsa_mixer(void)
6699{
6700 struct snd_card *card;
6701 struct tpacpi_alsa_data *data;
6702 struct snd_kcontrol *ctl_vol;
6703 struct snd_kcontrol *ctl_mute;
6704 int rc;
6705
6706 rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
6707 sizeof(struct tpacpi_alsa_data), &card);
6708 if (rc < 0)
6709 return rc;
6710 if (!card)
6711 return -ENOMEM;
6712
6713 BUG_ON(!card->private_data);
6714 data = card->private_data;
6715 data->card = card;
6716
6717 strlcpy(card->driver, TPACPI_ALSA_DRVNAME,
6718 sizeof(card->driver));
6719 strlcpy(card->shortname, TPACPI_ALSA_SHRTNAME,
6720 sizeof(card->shortname));
6721 snprintf(card->mixername, sizeof(card->mixername), "ThinkPad EC %s",
6722 (thinkpad_id.ec_version_str) ?
6723 thinkpad_id.ec_version_str : "(unknown)");
6724 snprintf(card->longname, sizeof(card->longname),
6725 "%s at EC reg 0x%02x, fw %s", card->shortname, TP_EC_AUDIO,
6726 (thinkpad_id.ec_version_str) ?
6727 thinkpad_id.ec_version_str : "unknown");
6728
6729 if (volume_control_allowed) {
6730 volume_alsa_control_vol.put = volume_alsa_vol_put;
6731 volume_alsa_control_vol.access =
6732 SNDRV_CTL_ELEM_ACCESS_READWRITE;
6733
6734 volume_alsa_control_mute.put = volume_alsa_mute_put;
6735 volume_alsa_control_mute.access =
6736 SNDRV_CTL_ELEM_ACCESS_READWRITE;
6737 }
6738
6739 if (!tp_features.mixer_no_level_control) {
6740 ctl_vol = snd_ctl_new1(&volume_alsa_control_vol, NULL);
6741 rc = snd_ctl_add(card, ctl_vol);
6742 if (rc < 0) {
6743 printk(TPACPI_ERR
6744 "Failed to create ALSA volume control\n");
6745 goto err_out;
6413 } 6746 }
6747 data->ctl_vol_id = &ctl_vol->id;
6748 }
6414 6749
6415 if (new_mute != mute) { 6750 ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL);
6416 /* level doesn't change */ 6751 rc = snd_ctl_add(card, ctl_mute);
6752 if (rc < 0) {
6753 printk(TPACPI_ERR "Failed to create ALSA mute control\n");
6754 goto err_out;
6755 }
6756 data->ctl_mute_id = &ctl_mute->id;
6417 6757
6418 cmos_cmd = (new_mute) ? 6758 snd_card_set_dev(card, &tpacpi_pdev->dev);
6419 TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP; 6759 rc = snd_card_register(card);
6420 6760
6421 if (issue_thinkpad_cmos_command(cmos_cmd) || 6761err_out:
6422 !acpi_ec_write(volume_offset, level + new_mute)) 6762 if (rc < 0) {
6423 return -EIO; 6763 snd_card_free(card);
6764 card = NULL;
6765 }
6766
6767 alsa_card = card;
6768 return rc;
6769}
6770
6771#define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */
6772#define TPACPI_VOL_Q_LEVEL 0x0002 /* Volume control available */
6773
6774static const struct tpacpi_quirk volume_quirk_table[] __initconst = {
6775 /* Whitelist volume level on all IBM by default */
6776 { .vendor = PCI_VENDOR_ID_IBM,
6777 .bios = TPACPI_MATCH_ANY,
6778 .ec = TPACPI_MATCH_ANY,
6779 .quirks = TPACPI_VOL_Q_LEVEL },
6780
6781 /* Lenovo models with volume control (needs confirmation) */
6782 TPACPI_QEC_LNV('7', 'C', TPACPI_VOL_Q_LEVEL), /* R60/i */
6783 TPACPI_QEC_LNV('7', 'E', TPACPI_VOL_Q_LEVEL), /* R60e/i */
6784 TPACPI_QEC_LNV('7', '9', TPACPI_VOL_Q_LEVEL), /* T60/p */
6785 TPACPI_QEC_LNV('7', 'B', TPACPI_VOL_Q_LEVEL), /* X60/s */
6786 TPACPI_QEC_LNV('7', 'J', TPACPI_VOL_Q_LEVEL), /* X60t */
6787 TPACPI_QEC_LNV('7', '7', TPACPI_VOL_Q_LEVEL), /* Z60 */
6788 TPACPI_QEC_LNV('7', 'F', TPACPI_VOL_Q_LEVEL), /* Z61 */
6789
6790 /* Whitelist mute-only on all Lenovo by default */
6791 { .vendor = PCI_VENDOR_ID_LENOVO,
6792 .bios = TPACPI_MATCH_ANY,
6793 .ec = TPACPI_MATCH_ANY,
6794 .quirks = TPACPI_VOL_Q_MUTEONLY }
6795};
6796
6797static int __init volume_init(struct ibm_init_struct *iibm)
6798{
6799 unsigned long quirks;
6800 int rc;
6801
6802 vdbg_printk(TPACPI_DBG_INIT, "initializing volume subdriver\n");
6803
6804 mutex_init(&volume_mutex);
6805
6806 /*
6807 * Check for module parameter bogosity, note that we
6808 * init volume_mode to TPACPI_VOL_MODE_MAX in order to be
6809 * able to detect "unspecified"
6810 */
6811 if (volume_mode > TPACPI_VOL_MODE_MAX)
6812 return -EINVAL;
6813
6814 if (volume_mode == TPACPI_VOL_MODE_UCMS_STEP) {
6815 printk(TPACPI_ERR
6816 "UCMS step volume mode not implemented, "
6817 "please contact %s\n", TPACPI_MAIL);
6818 return 1;
6819 }
6820
6821 if (volume_capabilities >= TPACPI_VOL_CAP_MAX)
6822 return -EINVAL;
6823
6824 /*
6825 * The ALSA mixer is our primary interface.
6826 * When disabled, don't install the subdriver at all
6827 */
6828 if (!alsa_enable) {
6829 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6830 "ALSA mixer disabled by parameter, "
6831 "not loading volume subdriver...\n");
6832 return 1;
6833 }
6834
6835 quirks = tpacpi_check_quirks(volume_quirk_table,
6836 ARRAY_SIZE(volume_quirk_table));
6837
6838 switch (volume_capabilities) {
6839 case TPACPI_VOL_CAP_AUTO:
6840 if (quirks & TPACPI_VOL_Q_MUTEONLY)
6841 tp_features.mixer_no_level_control = 1;
6842 else if (quirks & TPACPI_VOL_Q_LEVEL)
6843 tp_features.mixer_no_level_control = 0;
6844 else
6845 return 1; /* no mixer */
6846 break;
6847 case TPACPI_VOL_CAP_VOLMUTE:
6848 tp_features.mixer_no_level_control = 0;
6849 break;
6850 case TPACPI_VOL_CAP_MUTEONLY:
6851 tp_features.mixer_no_level_control = 1;
6852 break;
6853 default:
6854 return 1;
6855 }
6856
6857 if (volume_capabilities != TPACPI_VOL_CAP_AUTO)
6858 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6859 "using user-supplied volume_capabilities=%d\n",
6860 volume_capabilities);
6861
6862 if (volume_mode == TPACPI_VOL_MODE_AUTO ||
6863 volume_mode == TPACPI_VOL_MODE_MAX) {
6864 volume_mode = TPACPI_VOL_MODE_ECNVRAM;
6865
6866 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6867 "driver auto-selected volume_mode=%d\n",
6868 volume_mode);
6869 } else {
6870 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6871 "using user-supplied volume_mode=%d\n",
6872 volume_mode);
6873 }
6874
6875 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6876 "mute is supported, volume control is %s\n",
6877 str_supported(!tp_features.mixer_no_level_control));
6878
6879 rc = volume_create_alsa_mixer();
6880 if (rc) {
6881 printk(TPACPI_ERR
6882 "Could not create the ALSA mixer interface\n");
6883 return rc;
6884 }
6885
6886 printk(TPACPI_INFO
6887 "Console audio control enabled, mode: %s\n",
6888 (volume_control_allowed) ?
6889 "override (read/write)" :
6890 "monitor (read only)");
6891
6892 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6893 "registering volume hotkeys as change notification\n");
6894 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
6895 | TP_ACPI_HKEY_VOLUP_MASK
6896 | TP_ACPI_HKEY_VOLDWN_MASK
6897 | TP_ACPI_HKEY_MUTE_MASK);
6898
6899 return 0;
6900}
6901
6902static int volume_read(struct seq_file *m)
6903{
6904 u8 status;
6905
6906 if (volume_get_status(&status) < 0) {
6907 seq_printf(m, "level:\t\tunreadable\n");
6908 } else {
6909 if (tp_features.mixer_no_level_control)
6910 seq_printf(m, "level:\t\tunsupported\n");
6911 else
6912 seq_printf(m, "level:\t\t%d\n",
6913 status & TP_EC_AUDIO_LVL_MSK);
6914
6915 seq_printf(m, "mute:\t\t%s\n",
6916 onoff(status, TP_EC_AUDIO_MUTESW));
6917
6918 if (volume_control_allowed) {
6919 seq_printf(m, "commands:\tunmute, mute\n");
6920 if (!tp_features.mixer_no_level_control) {
6921 seq_printf(m,
6922 "commands:\tup, down\n");
6923 seq_printf(m,
6924 "commands:\tlevel <level>"
6925 " (<level> is 0-%d)\n",
6926 TP_EC_VOLUME_MAX);
6927 }
6424 } 6928 }
6425 } 6929 }
6426 6930
6427 return 0; 6931 return 0;
6428} 6932}
6429 6933
6934static int volume_write(char *buf)
6935{
6936 u8 s;
6937 u8 new_level, new_mute;
6938 int l;
6939 char *cmd;
6940 int rc;
6941
6942 /*
6943 * We do allow volume control at driver startup, so that the
6944 * user can set initial state through the volume=... parameter hack.
6945 */
6946 if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT) {
6947 if (unlikely(!tp_warned.volume_ctrl_forbidden)) {
6948 tp_warned.volume_ctrl_forbidden = 1;
6949 printk(TPACPI_NOTICE
6950 "Console audio control in monitor mode, "
6951 "changes are not allowed.\n");
6952 printk(TPACPI_NOTICE
6953 "Use the volume_control=1 module parameter "
6954 "to enable volume control\n");
6955 }
6956 return -EPERM;
6957 }
6958
6959 rc = volume_get_status(&s);
6960 if (rc < 0)
6961 return rc;
6962
6963 new_level = s & TP_EC_AUDIO_LVL_MSK;
6964 new_mute = s & TP_EC_AUDIO_MUTESW_MSK;
6965
6966 while ((cmd = next_cmd(&buf))) {
6967 if (!tp_features.mixer_no_level_control) {
6968 if (strlencmp(cmd, "up") == 0) {
6969 if (new_mute)
6970 new_mute = 0;
6971 else if (new_level < TP_EC_VOLUME_MAX)
6972 new_level++;
6973 continue;
6974 } else if (strlencmp(cmd, "down") == 0) {
6975 if (new_mute)
6976 new_mute = 0;
6977 else if (new_level > 0)
6978 new_level--;
6979 continue;
6980 } else if (sscanf(cmd, "level %u", &l) == 1 &&
6981 l >= 0 && l <= TP_EC_VOLUME_MAX) {
6982 new_level = l;
6983 continue;
6984 }
6985 }
6986 if (strlencmp(cmd, "mute") == 0)
6987 new_mute = TP_EC_AUDIO_MUTESW_MSK;
6988 else if (strlencmp(cmd, "unmute") == 0)
6989 new_mute = 0;
6990 else
6991 return -EINVAL;
6992 }
6993
6994 if (tp_features.mixer_no_level_control) {
6995 tpacpi_disclose_usertask("procfs volume", "%smute\n",
6996 new_mute ? "" : "un");
6997 rc = volume_set_mute(!!new_mute);
6998 } else {
6999 tpacpi_disclose_usertask("procfs volume",
7000 "%smute and set level to %d\n",
7001 new_mute ? "" : "un", new_level);
7002 rc = volume_set_status(new_mute | new_level);
7003 }
7004 volume_alsa_notify_change();
7005
7006 return (rc == -EINTR) ? -ERESTARTSYS : rc;
7007}
7008
6430static struct ibm_struct volume_driver_data = { 7009static struct ibm_struct volume_driver_data = {
6431 .name = "volume", 7010 .name = "volume",
6432 .read = volume_read, 7011 .read = volume_read,
6433 .write = volume_write, 7012 .write = volume_write,
7013 .exit = volume_exit,
7014 .suspend = volume_suspend,
7015 .resume = volume_resume,
7016 .shutdown = volume_shutdown,
6434}; 7017};
6435 7018
6436/************************************************************************* 7019/*************************************************************************
@@ -7507,9 +8090,8 @@ static void fan_resume(void)
7507 } 8090 }
7508} 8091}
7509 8092
7510static int fan_read(char *p) 8093static int fan_read(struct seq_file *m)
7511{ 8094{
7512 int len = 0;
7513 int rc; 8095 int rc;
7514 u8 status; 8096 u8 status;
7515 unsigned int speed = 0; 8097 unsigned int speed = 0;
@@ -7521,7 +8103,7 @@ static int fan_read(char *p)
7521 if (rc < 0) 8103 if (rc < 0)
7522 return rc; 8104 return rc;
7523 8105
7524 len += sprintf(p + len, "status:\t\t%s\n" 8106 seq_printf(m, "status:\t\t%s\n"
7525 "level:\t\t%d\n", 8107 "level:\t\t%d\n",
7526 (status != 0) ? "enabled" : "disabled", status); 8108 (status != 0) ? "enabled" : "disabled", status);
7527 break; 8109 break;
@@ -7532,54 +8114,54 @@ static int fan_read(char *p)
7532 if (rc < 0) 8114 if (rc < 0)
7533 return rc; 8115 return rc;
7534 8116
7535 len += sprintf(p + len, "status:\t\t%s\n", 8117 seq_printf(m, "status:\t\t%s\n",
7536 (status != 0) ? "enabled" : "disabled"); 8118 (status != 0) ? "enabled" : "disabled");
7537 8119
7538 rc = fan_get_speed(&speed); 8120 rc = fan_get_speed(&speed);
7539 if (rc < 0) 8121 if (rc < 0)
7540 return rc; 8122 return rc;
7541 8123
7542 len += sprintf(p + len, "speed:\t\t%d\n", speed); 8124 seq_printf(m, "speed:\t\t%d\n", speed);
7543 8125
7544 if (status & TP_EC_FAN_FULLSPEED) 8126 if (status & TP_EC_FAN_FULLSPEED)
7545 /* Disengaged mode takes precedence */ 8127 /* Disengaged mode takes precedence */
7546 len += sprintf(p + len, "level:\t\tdisengaged\n"); 8128 seq_printf(m, "level:\t\tdisengaged\n");
7547 else if (status & TP_EC_FAN_AUTO) 8129 else if (status & TP_EC_FAN_AUTO)
7548 len += sprintf(p + len, "level:\t\tauto\n"); 8130 seq_printf(m, "level:\t\tauto\n");
7549 else 8131 else
7550 len += sprintf(p + len, "level:\t\t%d\n", status); 8132 seq_printf(m, "level:\t\t%d\n", status);
7551 break; 8133 break;
7552 8134
7553 case TPACPI_FAN_NONE: 8135 case TPACPI_FAN_NONE:
7554 default: 8136 default:
7555 len += sprintf(p + len, "status:\t\tnot supported\n"); 8137 seq_printf(m, "status:\t\tnot supported\n");
7556 } 8138 }
7557 8139
7558 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) { 8140 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
7559 len += sprintf(p + len, "commands:\tlevel <level>"); 8141 seq_printf(m, "commands:\tlevel <level>");
7560 8142
7561 switch (fan_control_access_mode) { 8143 switch (fan_control_access_mode) {
7562 case TPACPI_FAN_WR_ACPI_SFAN: 8144 case TPACPI_FAN_WR_ACPI_SFAN:
7563 len += sprintf(p + len, " (<level> is 0-7)\n"); 8145 seq_printf(m, " (<level> is 0-7)\n");
7564 break; 8146 break;
7565 8147
7566 default: 8148 default:
7567 len += sprintf(p + len, " (<level> is 0-7, " 8149 seq_printf(m, " (<level> is 0-7, "
7568 "auto, disengaged, full-speed)\n"); 8150 "auto, disengaged, full-speed)\n");
7569 break; 8151 break;
7570 } 8152 }
7571 } 8153 }
7572 8154
7573 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE) 8155 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
7574 len += sprintf(p + len, "commands:\tenable, disable\n" 8156 seq_printf(m, "commands:\tenable, disable\n"
7575 "commands:\twatchdog <timeout> (<timeout> " 8157 "commands:\twatchdog <timeout> (<timeout> "
7576 "is 0 (off), 1-120 (seconds))\n"); 8158 "is 0 (off), 1-120 (seconds))\n");
7577 8159
7578 if (fan_control_commands & TPACPI_FAN_CMD_SPEED) 8160 if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
7579 len += sprintf(p + len, "commands:\tspeed <speed>" 8161 seq_printf(m, "commands:\tspeed <speed>"
7580 " (<speed> is 0-65535)\n"); 8162 " (<speed> is 0-65535)\n");
7581 8163
7582 return len; 8164 return 0;
7583} 8165}
7584 8166
7585static int fan_write_cmd_level(const char *cmd, int *rc) 8167static int fan_write_cmd_level(const char *cmd, int *rc)
@@ -7721,10 +8303,23 @@ static struct ibm_struct fan_driver_data = {
7721 */ 8303 */
7722static void tpacpi_driver_event(const unsigned int hkey_event) 8304static void tpacpi_driver_event(const unsigned int hkey_event)
7723{ 8305{
8306 if (ibm_backlight_device) {
8307 switch (hkey_event) {
8308 case TP_HKEY_EV_BRGHT_UP:
8309 case TP_HKEY_EV_BRGHT_DOWN:
8310 tpacpi_brightness_notify_change();
8311 }
8312 }
8313 if (alsa_card) {
8314 switch (hkey_event) {
8315 case TP_HKEY_EV_VOL_UP:
8316 case TP_HKEY_EV_VOL_DOWN:
8317 case TP_HKEY_EV_VOL_MUTE:
8318 volume_alsa_notify_change();
8319 }
8320 }
7724} 8321}
7725 8322
7726
7727
7728static void hotkey_driver_event(const unsigned int scancode) 8323static void hotkey_driver_event(const unsigned int scancode)
7729{ 8324{
7730 tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode); 8325 tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode);
@@ -7853,19 +8448,19 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
7853 "%s installed\n", ibm->name); 8448 "%s installed\n", ibm->name);
7854 8449
7855 if (ibm->read) { 8450 if (ibm->read) {
7856 entry = create_proc_entry(ibm->name, 8451 mode_t mode;
7857 S_IFREG | S_IRUGO | S_IWUSR, 8452
7858 proc_dir); 8453 mode = S_IRUGO;
8454 if (ibm->write)
8455 mode |= S_IWUSR;
8456 entry = proc_create_data(ibm->name, mode, proc_dir,
8457 &dispatch_proc_fops, ibm);
7859 if (!entry) { 8458 if (!entry) {
7860 printk(TPACPI_ERR "unable to create proc entry %s\n", 8459 printk(TPACPI_ERR "unable to create proc entry %s\n",
7861 ibm->name); 8460 ibm->name);
7862 ret = -ENODEV; 8461 ret = -ENODEV;
7863 goto err_out; 8462 goto err_out;
7864 } 8463 }
7865 entry->data = ibm;
7866 entry->read_proc = &dispatch_procfs_read;
7867 if (ibm->write)
7868 entry->write_proc = &dispatch_procfs_write;
7869 ibm->flags.proc_created = 1; 8464 ibm->flags.proc_created = 1;
7870 } 8465 }
7871 8466
@@ -8077,6 +8672,7 @@ static struct ibm_init_struct ibms_init[] __initdata = {
8077 .data = &brightness_driver_data, 8672 .data = &brightness_driver_data,
8078 }, 8673 },
8079 { 8674 {
8675 .init = volume_init,
8080 .data = &volume_driver_data, 8676 .data = &volume_driver_data,
8081 }, 8677 },
8082 { 8678 {
@@ -8112,36 +8708,59 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp)
8112 return -EINVAL; 8708 return -EINVAL;
8113} 8709}
8114 8710
8115module_param(experimental, int, 0); 8711module_param(experimental, int, 0444);
8116MODULE_PARM_DESC(experimental, 8712MODULE_PARM_DESC(experimental,
8117 "Enables experimental features when non-zero"); 8713 "Enables experimental features when non-zero");
8118 8714
8119module_param_named(debug, dbg_level, uint, 0); 8715module_param_named(debug, dbg_level, uint, 0);
8120MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); 8716MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
8121 8717
8122module_param(force_load, bool, 0); 8718module_param(force_load, bool, 0444);
8123MODULE_PARM_DESC(force_load, 8719MODULE_PARM_DESC(force_load,
8124 "Attempts to load the driver even on a " 8720 "Attempts to load the driver even on a "
8125 "mis-identified ThinkPad when true"); 8721 "mis-identified ThinkPad when true");
8126 8722
8127module_param_named(fan_control, fan_control_allowed, bool, 0); 8723module_param_named(fan_control, fan_control_allowed, bool, 0444);
8128MODULE_PARM_DESC(fan_control, 8724MODULE_PARM_DESC(fan_control,
8129 "Enables setting fan parameters features when true"); 8725 "Enables setting fan parameters features when true");
8130 8726
8131module_param_named(brightness_mode, brightness_mode, uint, 0); 8727module_param_named(brightness_mode, brightness_mode, uint, 0444);
8132MODULE_PARM_DESC(brightness_mode, 8728MODULE_PARM_DESC(brightness_mode,
8133 "Selects brightness control strategy: " 8729 "Selects brightness control strategy: "
8134 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM"); 8730 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
8135 8731
8136module_param(brightness_enable, uint, 0); 8732module_param(brightness_enable, uint, 0444);
8137MODULE_PARM_DESC(brightness_enable, 8733MODULE_PARM_DESC(brightness_enable,
8138 "Enables backlight control when 1, disables when 0"); 8734 "Enables backlight control when 1, disables when 0");
8139 8735
8140module_param(hotkey_report_mode, uint, 0); 8736module_param(hotkey_report_mode, uint, 0444);
8141MODULE_PARM_DESC(hotkey_report_mode, 8737MODULE_PARM_DESC(hotkey_report_mode,
8142 "used for backwards compatibility with userspace, " 8738 "used for backwards compatibility with userspace, "
8143 "see documentation"); 8739 "see documentation");
8144 8740
8741module_param_named(volume_mode, volume_mode, uint, 0444);
8742MODULE_PARM_DESC(volume_mode,
8743 "Selects volume control strategy: "
8744 "0=auto, 1=EC, 2=N/A, 3=EC+NVRAM");
8745
8746module_param_named(volume_capabilities, volume_capabilities, uint, 0444);
8747MODULE_PARM_DESC(volume_capabilities,
8748 "Selects the mixer capabilites: "
8749 "0=auto, 1=volume and mute, 2=mute only");
8750
8751module_param_named(volume_control, volume_control_allowed, bool, 0444);
8752MODULE_PARM_DESC(volume_control,
8753 "Enables software override for the console audio "
8754 "control when true");
8755
8756/* ALSA module API parameters */
8757module_param_named(index, alsa_index, int, 0444);
8758MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer");
8759module_param_named(id, alsa_id, charp, 0444);
8760MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer");
8761module_param_named(enable, alsa_enable, bool, 0444);
8762MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer");
8763
8145#define TPACPI_PARAM(feature) \ 8764#define TPACPI_PARAM(feature) \
8146 module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ 8765 module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
8147 MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \ 8766 MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \
@@ -8160,25 +8779,25 @@ TPACPI_PARAM(volume);
8160TPACPI_PARAM(fan); 8779TPACPI_PARAM(fan);
8161 8780
8162#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 8781#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
8163module_param(dbg_wlswemul, uint, 0); 8782module_param(dbg_wlswemul, uint, 0444);
8164MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation"); 8783MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
8165module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0); 8784module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
8166MODULE_PARM_DESC(wlsw_state, 8785MODULE_PARM_DESC(wlsw_state,
8167 "Initial state of the emulated WLSW switch"); 8786 "Initial state of the emulated WLSW switch");
8168 8787
8169module_param(dbg_bluetoothemul, uint, 0); 8788module_param(dbg_bluetoothemul, uint, 0444);
8170MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation"); 8789MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
8171module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0); 8790module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
8172MODULE_PARM_DESC(bluetooth_state, 8791MODULE_PARM_DESC(bluetooth_state,
8173 "Initial state of the emulated bluetooth switch"); 8792 "Initial state of the emulated bluetooth switch");
8174 8793
8175module_param(dbg_wwanemul, uint, 0); 8794module_param(dbg_wwanemul, uint, 0444);
8176MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation"); 8795MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
8177module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0); 8796module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
8178MODULE_PARM_DESC(wwan_state, 8797MODULE_PARM_DESC(wwan_state,
8179 "Initial state of the emulated WWAN switch"); 8798 "Initial state of the emulated WWAN switch");
8180 8799
8181module_param(dbg_uwbemul, uint, 0); 8800module_param(dbg_uwbemul, uint, 0444);
8182MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation"); 8801MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
8183module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0); 8802module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
8184MODULE_PARM_DESC(uwb_state, 8803MODULE_PARM_DESC(uwb_state,
@@ -8371,6 +8990,7 @@ static int __init thinkpad_acpi_module_init(void)
8371 PCI_VENDOR_ID_IBM; 8990 PCI_VENDOR_ID_IBM;
8372 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; 8991 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
8373 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 8992 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
8993 tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
8374 } 8994 }
8375 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 8995 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
8376 ret = ibm_init(&ibms_init[i]); 8996 ret = ibm_init(&ibms_init[i]);