aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2007-10-12 21:27:47 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2007-10-12 21:27:47 -0400
commitb981d8b3f5e008ff10d993be633ad00564fc22cd (patch)
treee292dc07b22308912cf6a58354a608b9e5e8e1fd /drivers/misc
parentb11d2127c4893a7315d1e16273bc8560049fa3ca (diff)
parent2b9e0aae1d50e880c58d46788e5e3ebd89d75d62 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/macintosh/adbhid.c
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig7
-rw-r--r--drivers/misc/asus-laptop.c45
-rw-r--r--drivers/misc/hdpuftrs/hdpu_cpustate.c107
-rw-r--r--drivers/misc/hdpuftrs/hdpu_nexus.c88
-rw-r--r--drivers/misc/ibmasm/command.c6
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c3
-rw-r--r--drivers/misc/ibmasm/module.c3
-rw-r--r--drivers/misc/msi-laptop.c4
-rw-r--r--drivers/misc/sony-laptop.c420
-rw-r--r--drivers/misc/thinkpad_acpi.c690
-rw-r--r--drivers/misc/thinkpad_acpi.h47
-rw-r--r--drivers/misc/tifm_core.c9
12 files changed, 1156 insertions, 273 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1d516f24ba53..73e248fb2ff1 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -5,6 +5,11 @@
5menuconfig MISC_DEVICES 5menuconfig MISC_DEVICES
6 bool "Misc devices" 6 bool "Misc devices"
7 default y 7 default y
8 ---help---
9 Say Y here to get to see options for device drivers from various
10 different categories. This option alone does not add any kernel code.
11
12 If you say N, all options in this submenu will be skipped and disabled.
8 13
9if MISC_DEVICES 14if MISC_DEVICES
10 15
@@ -150,6 +155,7 @@ config THINKPAD_ACPI
150 depends on X86 && ACPI 155 depends on X86 && ACPI
151 select BACKLIGHT_CLASS_DEVICE 156 select BACKLIGHT_CLASS_DEVICE
152 select HWMON 157 select HWMON
158 select NVRAM
153 ---help--- 159 ---help---
154 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds 160 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
155 support for Fn-Fx key combinations, Bluetooth control, video 161 support for Fn-Fx key combinations, Bluetooth control, video
@@ -196,4 +202,5 @@ config THINKPAD_ACPI_BAY
196 202
197 If you are not sure, say Y here. 203 If you are not sure, say Y here.
198 204
205
199endif # MISC_DEVICES 206endif # MISC_DEVICES
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 7798f590e5aa..7dce318df1bd 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -53,7 +53,6 @@
53#define ASUS_HOTK_NAME "Asus Laptop Support" 53#define ASUS_HOTK_NAME "Asus Laptop Support"
54#define ASUS_HOTK_CLASS "hotkey" 54#define ASUS_HOTK_CLASS "hotkey"
55#define ASUS_HOTK_DEVICE_NAME "Hotkey" 55#define ASUS_HOTK_DEVICE_NAME "Hotkey"
56#define ASUS_HOTK_HID "ATK0100"
57#define ASUS_HOTK_FILE "asus-laptop" 56#define ASUS_HOTK_FILE "asus-laptop"
58#define ASUS_HOTK_PREFIX "\\_SB.ATKD." 57#define ASUS_HOTK_PREFIX "\\_SB.ATKD."
59 58
@@ -197,12 +196,18 @@ static struct asus_hotk *hotk;
197/* 196/*
198 * The hotkey driver declaration 197 * The hotkey driver declaration
199 */ 198 */
199static const struct acpi_device_id asus_device_ids[] = {
200 {"ATK0100", 0},
201 {"", 0},
202};
203MODULE_DEVICE_TABLE(acpi, asus_device_ids);
204
200static int asus_hotk_add(struct acpi_device *device); 205static int asus_hotk_add(struct acpi_device *device);
201static int asus_hotk_remove(struct acpi_device *device, int type); 206static int asus_hotk_remove(struct acpi_device *device, int type);
202static struct acpi_driver asus_hotk_driver = { 207static struct acpi_driver asus_hotk_driver = {
203 .name = ASUS_HOTK_NAME, 208 .name = ASUS_HOTK_NAME,
204 .class = ASUS_HOTK_CLASS, 209 .class = ASUS_HOTK_CLASS,
205 .ids = ASUS_HOTK_HID, 210 .ids = asus_device_ids,
206 .ops = { 211 .ops = {
207 .add = asus_hotk_add, 212 .add = asus_hotk_add,
208 .remove = asus_hotk_remove, 213 .remove = asus_hotk_remove,
@@ -727,7 +732,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
727 lcd_blank(FB_BLANK_POWERDOWN); 732 lcd_blank(FB_BLANK_POWERDOWN);
728 } 733 }
729 734
730 acpi_bus_generate_event(hotk->device, event, 735 acpi_bus_generate_proc_event(hotk->device, event,
731 hotk->event_count[event % 128]++); 736 hotk->event_count[event % 128]++);
732 737
733 return; 738 return;
@@ -979,10 +984,9 @@ static int asus_hotk_add(struct acpi_device *device)
979 printk(ASUS_NOTICE "Asus Laptop Support version %s\n", 984 printk(ASUS_NOTICE "Asus Laptop Support version %s\n",
980 ASUS_LAPTOP_VERSION); 985 ASUS_LAPTOP_VERSION);
981 986
982 hotk = kmalloc(sizeof(struct asus_hotk), GFP_KERNEL); 987 hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
983 if (!hotk) 988 if (!hotk)
984 return -ENOMEM; 989 return -ENOMEM;
985 memset(hotk, 0, sizeof(struct asus_hotk));
986 990
987 hotk->handle = device->handle; 991 hotk->handle = device->handle;
988 strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME); 992 strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
@@ -1068,19 +1072,17 @@ static void asus_backlight_exit(void)
1068} 1072}
1069 1073
1070#define ASUS_LED_UNREGISTER(object) \ 1074#define ASUS_LED_UNREGISTER(object) \
1071 if(object##_led.class_dev \ 1075 if (object##_led.dev) \
1072 && !IS_ERR(object##_led.class_dev)) \
1073 led_classdev_unregister(&object##_led) 1076 led_classdev_unregister(&object##_led)
1074 1077
1075static void asus_led_exit(void) 1078static void asus_led_exit(void)
1076{ 1079{
1080 destroy_workqueue(led_workqueue);
1077 ASUS_LED_UNREGISTER(mled); 1081 ASUS_LED_UNREGISTER(mled);
1078 ASUS_LED_UNREGISTER(tled); 1082 ASUS_LED_UNREGISTER(tled);
1079 ASUS_LED_UNREGISTER(pled); 1083 ASUS_LED_UNREGISTER(pled);
1080 ASUS_LED_UNREGISTER(rled); 1084 ASUS_LED_UNREGISTER(rled);
1081 ASUS_LED_UNREGISTER(gled); 1085 ASUS_LED_UNREGISTER(gled);
1082
1083 destroy_workqueue(led_workqueue);
1084} 1086}
1085 1087
1086static void __exit asus_laptop_exit(void) 1088static void __exit asus_laptop_exit(void)
@@ -1136,29 +1138,42 @@ static int asus_led_init(struct device *dev)
1136 1138
1137 rv = ASUS_LED_REGISTER(mled, dev); 1139 rv = ASUS_LED_REGISTER(mled, dev);
1138 if (rv) 1140 if (rv)
1139 return rv; 1141 goto out;
1140 1142
1141 rv = ASUS_LED_REGISTER(tled, dev); 1143 rv = ASUS_LED_REGISTER(tled, dev);
1142 if (rv) 1144 if (rv)
1143 return rv; 1145 goto out1;
1144 1146
1145 rv = ASUS_LED_REGISTER(rled, dev); 1147 rv = ASUS_LED_REGISTER(rled, dev);
1146 if (rv) 1148 if (rv)
1147 return rv; 1149 goto out2;
1148 1150
1149 rv = ASUS_LED_REGISTER(pled, dev); 1151 rv = ASUS_LED_REGISTER(pled, dev);
1150 if (rv) 1152 if (rv)
1151 return rv; 1153 goto out3;
1152 1154
1153 rv = ASUS_LED_REGISTER(gled, dev); 1155 rv = ASUS_LED_REGISTER(gled, dev);
1154 if (rv) 1156 if (rv)
1155 return rv; 1157 goto out4;
1156 1158
1157 led_workqueue = create_singlethread_workqueue("led_workqueue"); 1159 led_workqueue = create_singlethread_workqueue("led_workqueue");
1158 if (!led_workqueue) 1160 if (!led_workqueue)
1159 return -ENOMEM; 1161 goto out5;
1160 1162
1161 return 0; 1163 return 0;
1164out5:
1165 rv = -ENOMEM;
1166 ASUS_LED_UNREGISTER(gled);
1167out4:
1168 ASUS_LED_UNREGISTER(pled);
1169out3:
1170 ASUS_LED_UNREGISTER(rled);
1171out2:
1172 ASUS_LED_UNREGISTER(tled);
1173out1:
1174 ASUS_LED_UNREGISTER(mled);
1175out:
1176 return rv;
1162} 1177}
1163 1178
1164static int __init asus_laptop_init(void) 1179static int __init asus_laptop_init(void)
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
index 276ba3c5143f..aa8ce7abe922 100644
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -19,16 +19,41 @@
19#include <linux/spinlock.h> 19#include <linux/spinlock.h>
20#include <linux/miscdevice.h> 20#include <linux/miscdevice.h>
21#include <linux/proc_fs.h> 21#include <linux/proc_fs.h>
22#include <linux/hdpu_features.h>
22#include <linux/platform_device.h> 23#include <linux/platform_device.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24#include <linux/hdpu_features.h> 25#include <linux/seq_file.h>
26#include <asm/io.h>
25 27
26#define SKY_CPUSTATE_VERSION "1.1" 28#define SKY_CPUSTATE_VERSION "1.1"
27 29
28static int hdpu_cpustate_probe(struct platform_device *pdev); 30static int hdpu_cpustate_probe(struct platform_device *pdev);
29static int hdpu_cpustate_remove(struct platform_device *pdev); 31static int hdpu_cpustate_remove(struct platform_device *pdev);
30 32
31struct cpustate_t cpustate; 33static unsigned char cpustate_get_state(void);
34static int cpustate_proc_open(struct inode *inode, struct file *file);
35static int cpustate_proc_read(struct seq_file *seq, void *offset);
36
37static struct cpustate_t cpustate;
38
39static const struct file_operations proc_cpustate = {
40 .open = cpustate_proc_open,
41 .read = seq_read,
42 .llseek = seq_lseek,
43 .release = single_release,
44 .owner = THIS_MODULE,
45};
46
47static int cpustate_proc_open(struct inode *inode, struct file *file)
48{
49 return single_open(file, cpustate_proc_read, NULL);
50}
51
52static int cpustate_proc_read(struct seq_file *seq, void *offset)
53{
54 seq_printf(seq, "CPU State: %04x\n", cpustate_get_state());
55 return 0;
56}
32 57
33static int cpustate_get_ref(int excl) 58static int cpustate_get_ref(int excl)
34{ 59{
@@ -66,13 +91,13 @@ static int cpustate_free_ref(void)
66 return 0; 91 return 0;
67} 92}
68 93
69unsigned char cpustate_get_state(void) 94static unsigned char cpustate_get_state(void)
70{ 95{
71 96
72 return cpustate.cached_val; 97 return cpustate.cached_val;
73} 98}
74 99
75void cpustate_set_state(unsigned char new_state) 100static void cpustate_set_state(unsigned char new_state)
76{ 101{
77 unsigned int state = (new_state << 21); 102 unsigned int state = (new_state << 21);
78 103
@@ -134,29 +159,6 @@ static int cpustate_release(struct inode *inode, struct file *file)
134 return cpustate_free_ref(); 159 return cpustate_free_ref();
135} 160}
136 161
137/*
138 * Info exported via "/proc/sky_cpustate".
139 */
140static int cpustate_read_proc(char *page, char **start, off_t off,
141 int count, int *eof, void *data)
142{
143 char *p = page;
144 int len = 0;
145
146 p += sprintf(p, "CPU State: %04x\n", cpustate_get_state());
147 len = p - page;
148
149 if (len <= off + count)
150 *eof = 1;
151 *start = page + off;
152 len -= off;
153 if (len > count)
154 len = count;
155 if (len < 0)
156 len = 0;
157 return len;
158}
159
160static struct platform_driver hdpu_cpustate_driver = { 162static struct platform_driver hdpu_cpustate_driver = {
161 .probe = hdpu_cpustate_probe, 163 .probe = hdpu_cpustate_probe,
162 .remove = hdpu_cpustate_remove, 164 .remove = hdpu_cpustate_remove,
@@ -169,22 +171,18 @@ static struct platform_driver hdpu_cpustate_driver = {
169 * The various file operations we support. 171 * The various file operations we support.
170 */ 172 */
171static const struct file_operations cpustate_fops = { 173static const struct file_operations cpustate_fops = {
172 owner:THIS_MODULE, 174 .owner = THIS_MODULE,
173 open:cpustate_open, 175 .open = cpustate_open,
174 release:cpustate_release, 176 .release = cpustate_release,
175 read:cpustate_read, 177 .read = cpustate_read,
176 write:cpustate_write, 178 .write = cpustate_write,
177 fasync:NULL, 179 .llseek = no_llseek,
178 poll:NULL,
179 ioctl:NULL,
180 llseek:no_llseek,
181
182}; 180};
183 181
184static struct miscdevice cpustate_dev = { 182static struct miscdevice cpustate_dev = {
185 MISC_DYNAMIC_MINOR, 183 .minor = MISC_DYNAMIC_MINOR,
186 "sky_cpustate", 184 .name = "sky_cpustate",
187 &cpustate_fops 185 .fops = &cpustate_fops,
188}; 186};
189 187
190static int hdpu_cpustate_probe(struct platform_device *pdev) 188static int hdpu_cpustate_probe(struct platform_device *pdev)
@@ -194,23 +192,31 @@ static int hdpu_cpustate_probe(struct platform_device *pdev)
194 int ret; 192 int ret;
195 193
196 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 194 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
195 if (!res) {
196 printk(KERN_ERR "sky_cpustate: "
197 "Invalid memory resource.\n");
198 return -EINVAL;
199 }
197 cpustate.set_addr = (unsigned long *)res->start; 200 cpustate.set_addr = (unsigned long *)res->start;
198 cpustate.clr_addr = (unsigned long *)res->end - 1; 201 cpustate.clr_addr = (unsigned long *)res->end - 1;
199 202
200 ret = misc_register(&cpustate_dev); 203 ret = misc_register(&cpustate_dev);
201 if (ret) { 204 if (ret) {
202 printk(KERN_WARNING "sky_cpustate: Unable to register misc " 205 printk(KERN_WARNING "sky_cpustate: "
203 "device.\n"); 206 "Unable to register misc device.\n");
204 cpustate.set_addr = NULL; 207 cpustate.set_addr = NULL;
205 cpustate.clr_addr = NULL; 208 cpustate.clr_addr = NULL;
206 return ret; 209 return ret;
207 } 210 }
208 211
209 proc_de = create_proc_read_entry("sky_cpustate", 0, 0, 212 proc_de = create_proc_entry("sky_cpustate", 0666, &proc_root);
210 cpustate_read_proc, NULL); 213 if (!proc_de) {
211 if (proc_de == NULL) 214 printk(KERN_WARNING "sky_cpustate: "
212 printk(KERN_WARNING "sky_cpustate: Unable to create proc " 215 "Unable to create proc entry\n");
213 "dir entry\n"); 216 } else {
217 proc_de->proc_fops = &proc_cpustate;
218 proc_de->owner = THIS_MODULE;
219 }
214 220
215 printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n"); 221 printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
216 return 0; 222 return 0;
@@ -218,21 +224,18 @@ static int hdpu_cpustate_probe(struct platform_device *pdev)
218 224
219static int hdpu_cpustate_remove(struct platform_device *pdev) 225static int hdpu_cpustate_remove(struct platform_device *pdev)
220{ 226{
221
222 cpustate.set_addr = NULL; 227 cpustate.set_addr = NULL;
223 cpustate.clr_addr = NULL; 228 cpustate.clr_addr = NULL;
224 229
225 remove_proc_entry("sky_cpustate", NULL); 230 remove_proc_entry("sky_cpustate", NULL);
226 misc_deregister(&cpustate_dev); 231 misc_deregister(&cpustate_dev);
227 return 0;
228 232
233 return 0;
229} 234}
230 235
231static int __init cpustate_init(void) 236static int __init cpustate_init(void)
232{ 237{
233 int rc; 238 return platform_driver_register(&hdpu_cpustate_driver);
234 rc = platform_driver_register(&hdpu_cpustate_driver);
235 return rc;
236} 239}
237 240
238static void __exit cpustate_exit(void) 241static void __exit cpustate_exit(void)
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
index 60c8b26f0678..2887b2147980 100644
--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
+++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
@@ -18,17 +18,38 @@
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/proc_fs.h> 19#include <linux/proc_fs.h>
20#include <linux/hdpu_features.h> 20#include <linux/hdpu_features.h>
21
22#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/seq_file.h>
23#include <asm/io.h>
23 24
24static int hdpu_nexus_probe(struct platform_device *pdev); 25static int hdpu_nexus_probe(struct platform_device *pdev);
25static int hdpu_nexus_remove(struct platform_device *pdev); 26static int hdpu_nexus_remove(struct platform_device *pdev);
27static int hdpu_slot_id_open(struct inode *inode, struct file *file);
28static int hdpu_slot_id_read(struct seq_file *seq, void *offset);
29static int hdpu_chassis_id_open(struct inode *inode, struct file *file);
30static int hdpu_chassis_id_read(struct seq_file *seq, void *offset);
26 31
27static struct proc_dir_entry *hdpu_slot_id; 32static struct proc_dir_entry *hdpu_slot_id;
28static struct proc_dir_entry *hdpu_chassis_id; 33static struct proc_dir_entry *hdpu_chassis_id;
29static int slot_id = -1; 34static int slot_id = -1;
30static int chassis_id = -1; 35static int chassis_id = -1;
31 36
37static const struct file_operations proc_slot_id = {
38 .open = hdpu_slot_id_open,
39 .read = seq_read,
40 .llseek = seq_lseek,
41 .release = single_release,
42 .owner = THIS_MODULE,
43};
44
45static const struct file_operations proc_chassis_id = {
46 .open = hdpu_chassis_id_open,
47 .read = seq_read,
48 .llseek = seq_lseek,
49 .release = single_release,
50 .owner = THIS_MODULE,
51};
52
32static struct platform_driver hdpu_nexus_driver = { 53static struct platform_driver hdpu_nexus_driver = {
33 .probe = hdpu_nexus_probe, 54 .probe = hdpu_nexus_probe,
34 .remove = hdpu_nexus_remove, 55 .remove = hdpu_nexus_remove,
@@ -37,43 +58,67 @@ static struct platform_driver hdpu_nexus_driver = {
37 }, 58 },
38}; 59};
39 60
40int hdpu_slot_id_read(char *buffer, char **buffer_location, off_t offset, 61static int hdpu_slot_id_open(struct inode *inode, struct file *file)
41 int buffer_length, int *zero, void *ptr)
42{ 62{
63 return single_open(file, hdpu_slot_id_read, NULL);
64}
43 65
44 if (offset > 0) 66static int hdpu_slot_id_read(struct seq_file *seq, void *offset)
45 return 0; 67{
46 return sprintf(buffer, "%d\n", slot_id); 68 seq_printf(seq, "%d\n", slot_id);
69 return 0;
47} 70}
48 71
49int hdpu_chassis_id_read(char *buffer, char **buffer_location, off_t offset, 72static int hdpu_chassis_id_open(struct inode *inode, struct file *file)
50 int buffer_length, int *zero, void *ptr)
51{ 73{
74 return single_open(file, hdpu_chassis_id_read, NULL);
75}
52 76
53 if (offset > 0) 77static int hdpu_chassis_id_read(struct seq_file *seq, void *offset)
54 return 0; 78{
55 return sprintf(buffer, "%d\n", chassis_id); 79 seq_printf(seq, "%d\n", chassis_id);
80 return 0;
56} 81}
57 82
58static int hdpu_nexus_probe(struct platform_device *pdev) 83static int hdpu_nexus_probe(struct platform_device *pdev)
59{ 84{
60 struct resource *res; 85 struct resource *res;
86 int *nexus_id_addr;
61 87
62 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 88 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
63 int *nexus_id_addr; 89 if (!res) {
64 nexus_id_addr = 90 printk(KERN_ERR "sky_nexus: "
65 ioremap(res->start, (unsigned long)(res->end - res->start)); 91 "Invalid memory resource.\n");
92 return -EINVAL;
93 }
94 nexus_id_addr = ioremap(res->start,
95 (unsigned long)(res->end - res->start));
66 if (nexus_id_addr) { 96 if (nexus_id_addr) {
67 slot_id = (*nexus_id_addr >> 8) & 0x1f; 97 slot_id = (*nexus_id_addr >> 8) & 0x1f;
68 chassis_id = *nexus_id_addr & 0xff; 98 chassis_id = *nexus_id_addr & 0xff;
69 iounmap(nexus_id_addr); 99 iounmap(nexus_id_addr);
70 } else 100 } else {
71 printk("Could not map slot id\n"); 101 printk(KERN_ERR "sky_nexus: Could not map slot id\n");
102 }
103
72 hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root); 104 hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root);
73 hdpu_slot_id->read_proc = hdpu_slot_id_read; 105 if (!hdpu_slot_id) {
106 printk(KERN_WARNING "sky_nexus: "
107 "Unable to create proc dir entry: sky_slot_id\n");
108 } else {
109 hdpu_slot_id->proc_fops = &proc_slot_id;
110 hdpu_slot_id->owner = THIS_MODULE;
111 }
74 112
75 hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root); 113 hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root);
76 hdpu_chassis_id->read_proc = hdpu_chassis_id_read; 114 if (!hdpu_chassis_id) {
115 printk(KERN_WARNING "sky_nexus: "
116 "Unable to create proc dir entry: sky_chassis_id\n");
117 } else {
118 hdpu_chassis_id->proc_fops = &proc_chassis_id;
119 hdpu_chassis_id->owner = THIS_MODULE;
120 }
121
77 return 0; 122 return 0;
78} 123}
79 124
@@ -81,18 +126,19 @@ static int hdpu_nexus_remove(struct platform_device *pdev)
81{ 126{
82 slot_id = -1; 127 slot_id = -1;
83 chassis_id = -1; 128 chassis_id = -1;
129
84 remove_proc_entry("sky_slot_id", &proc_root); 130 remove_proc_entry("sky_slot_id", &proc_root);
85 remove_proc_entry("sky_chassis_id", &proc_root); 131 remove_proc_entry("sky_chassis_id", &proc_root);
132
86 hdpu_slot_id = 0; 133 hdpu_slot_id = 0;
87 hdpu_chassis_id = 0; 134 hdpu_chassis_id = 0;
135
88 return 0; 136 return 0;
89} 137}
90 138
91static int __init nexus_init(void) 139static int __init nexus_init(void)
92{ 140{
93 int rc; 141 return platform_driver_register(&hdpu_nexus_driver);
94 rc = platform_driver_register(&hdpu_nexus_driver);
95 return rc;
96} 142}
97 143
98static void __exit nexus_exit(void) 144static void __exit nexus_exit(void)
diff --git a/drivers/misc/ibmasm/command.c b/drivers/misc/ibmasm/command.c
index b5df347c81b9..6497872df524 100644
--- a/drivers/misc/ibmasm/command.c
+++ b/drivers/misc/ibmasm/command.c
@@ -41,18 +41,16 @@ struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_s
41 if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE) 41 if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE)
42 return NULL; 42 return NULL;
43 43
44 cmd = kmalloc(sizeof(struct command), GFP_KERNEL); 44 cmd = kzalloc(sizeof(struct command), GFP_KERNEL);
45 if (cmd == NULL) 45 if (cmd == NULL)
46 return NULL; 46 return NULL;
47 47
48 memset(cmd, 0, sizeof(*cmd));
49 48
50 cmd->buffer = kmalloc(buffer_size, GFP_KERNEL); 49 cmd->buffer = kzalloc(buffer_size, GFP_KERNEL);
51 if (cmd->buffer == NULL) { 50 if (cmd->buffer == NULL) {
52 kfree(cmd); 51 kfree(cmd);
53 return NULL; 52 return NULL;
54 } 53 }
55 memset(cmd->buffer, 0, buffer_size);
56 cmd->buffer_size = buffer_size; 54 cmd->buffer_size = buffer_size;
57 55
58 kobject_init(&cmd->kobj); 56 kobject_init(&cmd->kobj);
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index eb7b073734b8..22a7e8ba211d 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -563,11 +563,10 @@ static ssize_t remote_settings_file_write(struct file *file, const char __user *
563 if (*offset != 0) 563 if (*offset != 0)
564 return 0; 564 return 0;
565 565
566 buff = kmalloc (count + 1, GFP_KERNEL); 566 buff = kzalloc (count + 1, GFP_KERNEL);
567 if (!buff) 567 if (!buff)
568 return -ENOMEM; 568 return -ENOMEM;
569 569
570 memset(buff, 0x0, count + 1);
571 570
572 if (copy_from_user(buff, ubuff, count)) { 571 if (copy_from_user(buff, ubuff, count)) {
573 kfree(buff); 572 kfree(buff);
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index fb03a853fac4..4f9d4a9da983 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -77,13 +77,12 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
77 /* vnc client won't work without bus-mastering */ 77 /* vnc client won't work without bus-mastering */
78 pci_set_master(pdev); 78 pci_set_master(pdev);
79 79
80 sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL); 80 sp = kzalloc(sizeof(struct service_processor), GFP_KERNEL);
81 if (sp == NULL) { 81 if (sp == NULL) {
82 dev_err(&pdev->dev, "Failed to allocate memory\n"); 82 dev_err(&pdev->dev, "Failed to allocate memory\n");
83 result = -ENOMEM; 83 result = -ENOMEM;
84 goto error_kmalloc; 84 goto error_kmalloc;
85 } 85 }
86 memset(sp, 0, sizeof(struct service_processor));
87 86
88 spin_lock_init(&sp->lock); 87 spin_lock_init(&sp->lock);
89 INIT_LIST_HEAD(&sp->command_queue); 88 INIT_LIST_HEAD(&sp->command_queue);
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 932a415197b3..83679c762925 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -283,7 +283,7 @@ static struct platform_device *msipf_device;
283 283
284/* Initialization */ 284/* Initialization */
285 285
286static int dmi_check_cb(struct dmi_system_id *id) 286static int dmi_check_cb(const struct dmi_system_id *id)
287{ 287{
288 printk("msi-laptop: Identified laptop model '%s'.\n", id->ident); 288 printk("msi-laptop: Identified laptop model '%s'.\n", id->ident);
289 return 0; 289 return 0;
@@ -353,7 +353,7 @@ static int __init msi_init(void)
353 if (IS_ERR(msibl_device)) 353 if (IS_ERR(msibl_device))
354 return PTR_ERR(msibl_device); 354 return PTR_ERR(msibl_device);
355 355
356 msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1, 356 msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1;
357 357
358 ret = platform_driver_register(&msipf_driver); 358 ret = platform_driver_register(&msipf_driver);
359 if (ret) 359 if (ret)
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 9623eaf4f89f..e73a71f04bb4 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -142,43 +142,124 @@ struct sony_laptop_keypress {
142 int key; 142 int key;
143}; 143};
144 144
145/* Correspondance table between sonypi events and input layer events */ 145/* Correspondance table between sonypi events
146static struct { 146 * and input layer indexes in the keymap
147 int sonypiev; 147 */
148 int inputev; 148static int sony_laptop_input_index[] = {
149} sony_laptop_inputkeys[] = { 149 -1, /* no event */
150 { SONYPI_EVENT_CAPTURE_PRESSED, KEY_CAMERA }, 150 -1, /* SONYPI_EVENT_JOGDIAL_DOWN */
151 { SONYPI_EVENT_FNKEY_ONLY, KEY_FN }, 151 -1, /* SONYPI_EVENT_JOGDIAL_UP */
152 { SONYPI_EVENT_FNKEY_ESC, KEY_FN_ESC }, 152 -1, /* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */
153 { SONYPI_EVENT_FNKEY_F1, KEY_FN_F1 }, 153 -1, /* SONYPI_EVENT_JOGDIAL_UP_PRESSED */
154 { SONYPI_EVENT_FNKEY_F2, KEY_FN_F2 }, 154 -1, /* SONYPI_EVENT_JOGDIAL_PRESSED */
155 { SONYPI_EVENT_FNKEY_F3, KEY_FN_F3 }, 155 -1, /* SONYPI_EVENT_JOGDIAL_RELEASED */
156 { SONYPI_EVENT_FNKEY_F4, KEY_FN_F4 }, 156 0, /* SONYPI_EVENT_CAPTURE_PRESSED */
157 { SONYPI_EVENT_FNKEY_F5, KEY_FN_F5 }, 157 1, /* SONYPI_EVENT_CAPTURE_RELEASED */
158 { SONYPI_EVENT_FNKEY_F6, KEY_FN_F6 }, 158 2, /* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
159 { SONYPI_EVENT_FNKEY_F7, KEY_FN_F7 }, 159 3, /* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
160 { SONYPI_EVENT_FNKEY_F8, KEY_FN_F8 }, 160 4, /* SONYPI_EVENT_FNKEY_ESC */
161 { SONYPI_EVENT_FNKEY_F9, KEY_FN_F9 }, 161 5, /* SONYPI_EVENT_FNKEY_F1 */
162 { SONYPI_EVENT_FNKEY_F10, KEY_FN_F10 }, 162 6, /* SONYPI_EVENT_FNKEY_F2 */
163 { SONYPI_EVENT_FNKEY_F11, KEY_FN_F11 }, 163 7, /* SONYPI_EVENT_FNKEY_F3 */
164 { SONYPI_EVENT_FNKEY_F12, KEY_FN_F12 }, 164 8, /* SONYPI_EVENT_FNKEY_F4 */
165 { SONYPI_EVENT_FNKEY_1, KEY_FN_1 }, 165 9, /* SONYPI_EVENT_FNKEY_F5 */
166 { SONYPI_EVENT_FNKEY_2, KEY_FN_2 }, 166 10, /* SONYPI_EVENT_FNKEY_F6 */
167 { SONYPI_EVENT_FNKEY_D, KEY_FN_D }, 167 11, /* SONYPI_EVENT_FNKEY_F7 */
168 { SONYPI_EVENT_FNKEY_E, KEY_FN_E }, 168 12, /* SONYPI_EVENT_FNKEY_F8 */
169 { SONYPI_EVENT_FNKEY_F, KEY_FN_F }, 169 13, /* SONYPI_EVENT_FNKEY_F9 */
170 { SONYPI_EVENT_FNKEY_S, KEY_FN_S }, 170 14, /* SONYPI_EVENT_FNKEY_F10 */
171 { SONYPI_EVENT_FNKEY_B, KEY_FN_B }, 171 15, /* SONYPI_EVENT_FNKEY_F11 */
172 { SONYPI_EVENT_BLUETOOTH_PRESSED, KEY_BLUE }, 172 16, /* SONYPI_EVENT_FNKEY_F12 */
173 { SONYPI_EVENT_BLUETOOTH_ON, KEY_BLUE }, 173 17, /* SONYPI_EVENT_FNKEY_1 */
174 { SONYPI_EVENT_PKEY_P1, KEY_PROG1 }, 174 18, /* SONYPI_EVENT_FNKEY_2 */
175 { SONYPI_EVENT_PKEY_P2, KEY_PROG2 }, 175 19, /* SONYPI_EVENT_FNKEY_D */
176 { SONYPI_EVENT_PKEY_P3, KEY_PROG3 }, 176 20, /* SONYPI_EVENT_FNKEY_E */
177 { SONYPI_EVENT_BACK_PRESSED, KEY_BACK }, 177 21, /* SONYPI_EVENT_FNKEY_F */
178 { SONYPI_EVENT_HELP_PRESSED, KEY_HELP }, 178 22, /* SONYPI_EVENT_FNKEY_S */
179 { SONYPI_EVENT_ZOOM_PRESSED, KEY_ZOOM }, 179 23, /* SONYPI_EVENT_FNKEY_B */
180 { SONYPI_EVENT_THUMBPHRASE_PRESSED, BTN_THUMB }, 180 24, /* SONYPI_EVENT_BLUETOOTH_PRESSED */
181 { 0, 0 }, 181 25, /* SONYPI_EVENT_PKEY_P1 */
182 26, /* SONYPI_EVENT_PKEY_P2 */
183 27, /* SONYPI_EVENT_PKEY_P3 */
184 28, /* SONYPI_EVENT_BACK_PRESSED */
185 -1, /* SONYPI_EVENT_LID_CLOSED */
186 -1, /* SONYPI_EVENT_LID_OPENED */
187 29, /* SONYPI_EVENT_BLUETOOTH_ON */
188 30, /* SONYPI_EVENT_BLUETOOTH_OFF */
189 31, /* SONYPI_EVENT_HELP_PRESSED */
190 32, /* SONYPI_EVENT_FNKEY_ONLY */
191 33, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN */
192 34, /* SONYPI_EVENT_JOGDIAL_FAST_UP */
193 35, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
194 36, /* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
195 37, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
196 38, /* SONYPI_EVENT_JOGDIAL_VFAST_UP */
197 39, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
198 40, /* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
199 41, /* SONYPI_EVENT_ZOOM_PRESSED */
200 42, /* SONYPI_EVENT_THUMBPHRASE_PRESSED */
201 43, /* SONYPI_EVENT_MEYE_FACE */
202 44, /* SONYPI_EVENT_MEYE_OPPOSITE */
203 45, /* SONYPI_EVENT_MEMORYSTICK_INSERT */
204 46, /* SONYPI_EVENT_MEMORYSTICK_EJECT */
205 -1, /* SONYPI_EVENT_ANYBUTTON_RELEASED */
206 -1, /* SONYPI_EVENT_BATTERY_INSERT */
207 -1, /* SONYPI_EVENT_BATTERY_REMOVE */
208 -1, /* SONYPI_EVENT_FNKEY_RELEASED */
209 47, /* SONYPI_EVENT_WIRELESS_ON */
210 48, /* SONYPI_EVENT_WIRELESS_OFF */
211};
212
213static int sony_laptop_input_keycode_map[] = {
214 KEY_CAMERA, /* 0 SONYPI_EVENT_CAPTURE_PRESSED */
215 KEY_RESERVED, /* 1 SONYPI_EVENT_CAPTURE_RELEASED */
216 KEY_RESERVED, /* 2 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
217 KEY_RESERVED, /* 3 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
218 KEY_FN_ESC, /* 4 SONYPI_EVENT_FNKEY_ESC */
219 KEY_FN_F1, /* 5 SONYPI_EVENT_FNKEY_F1 */
220 KEY_FN_F2, /* 6 SONYPI_EVENT_FNKEY_F2 */
221 KEY_FN_F3, /* 7 SONYPI_EVENT_FNKEY_F3 */
222 KEY_FN_F4, /* 8 SONYPI_EVENT_FNKEY_F4 */
223 KEY_FN_F5, /* 9 SONYPI_EVENT_FNKEY_F5 */
224 KEY_FN_F6, /* 10 SONYPI_EVENT_FNKEY_F6 */
225 KEY_FN_F7, /* 11 SONYPI_EVENT_FNKEY_F7 */
226 KEY_FN_F8, /* 12 SONYPI_EVENT_FNKEY_F8 */
227 KEY_FN_F9, /* 13 SONYPI_EVENT_FNKEY_F9 */
228 KEY_FN_F10, /* 14 SONYPI_EVENT_FNKEY_F10 */
229 KEY_FN_F11, /* 15 SONYPI_EVENT_FNKEY_F11 */
230 KEY_FN_F12, /* 16 SONYPI_EVENT_FNKEY_F12 */
231 KEY_FN_F1, /* 17 SONYPI_EVENT_FNKEY_1 */
232 KEY_FN_F2, /* 18 SONYPI_EVENT_FNKEY_2 */
233 KEY_FN_D, /* 19 SONYPI_EVENT_FNKEY_D */
234 KEY_FN_E, /* 20 SONYPI_EVENT_FNKEY_E */
235 KEY_FN_F, /* 21 SONYPI_EVENT_FNKEY_F */
236 KEY_FN_S, /* 22 SONYPI_EVENT_FNKEY_S */
237 KEY_FN_B, /* 23 SONYPI_EVENT_FNKEY_B */
238 KEY_BLUETOOTH, /* 24 SONYPI_EVENT_BLUETOOTH_PRESSED */
239 KEY_PROG1, /* 25 SONYPI_EVENT_PKEY_P1 */
240 KEY_PROG2, /* 26 SONYPI_EVENT_PKEY_P2 */
241 KEY_PROG3, /* 27 SONYPI_EVENT_PKEY_P3 */
242 KEY_BACK, /* 28 SONYPI_EVENT_BACK_PRESSED */
243 KEY_BLUETOOTH, /* 29 SONYPI_EVENT_BLUETOOTH_ON */
244 KEY_BLUETOOTH, /* 30 SONYPI_EVENT_BLUETOOTH_OFF */
245 KEY_HELP, /* 31 SONYPI_EVENT_HELP_PRESSED */
246 KEY_FN, /* 32 SONYPI_EVENT_FNKEY_ONLY */
247 KEY_RESERVED, /* 33 SONYPI_EVENT_JOGDIAL_FAST_DOWN */
248 KEY_RESERVED, /* 34 SONYPI_EVENT_JOGDIAL_FAST_UP */
249 KEY_RESERVED, /* 35 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
250 KEY_RESERVED, /* 36 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
251 KEY_RESERVED, /* 37 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
252 KEY_RESERVED, /* 38 SONYPI_EVENT_JOGDIAL_VFAST_UP */
253 KEY_RESERVED, /* 39 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
254 KEY_RESERVED, /* 40 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
255 KEY_ZOOM, /* 41 SONYPI_EVENT_ZOOM_PRESSED */
256 BTN_THUMB, /* 42 SONYPI_EVENT_THUMBPHRASE_PRESSED */
257 KEY_RESERVED, /* 43 SONYPI_EVENT_MEYE_FACE */
258 KEY_RESERVED, /* 44 SONYPI_EVENT_MEYE_OPPOSITE */
259 KEY_RESERVED, /* 45 SONYPI_EVENT_MEMORYSTICK_INSERT */
260 KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */
261 KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */
262 KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */
182}; 263};
183 264
184/* release buttons after a short delay if pressed */ 265/* release buttons after a short delay if pressed */
@@ -202,7 +283,6 @@ static void sony_laptop_report_input_event(u8 event)
202 struct input_dev *jog_dev = sony_laptop_input.jog_dev; 283 struct input_dev *jog_dev = sony_laptop_input.jog_dev;
203 struct input_dev *key_dev = sony_laptop_input.key_dev; 284 struct input_dev *key_dev = sony_laptop_input.key_dev;
204 struct sony_laptop_keypress kp = { NULL }; 285 struct sony_laptop_keypress kp = { NULL };
205 int i;
206 286
207 if (event == SONYPI_EVENT_FNKEY_RELEASED) { 287 if (event == SONYPI_EVENT_FNKEY_RELEASED) {
208 /* Nothing, not all VAIOs generate this event */ 288 /* Nothing, not all VAIOs generate this event */
@@ -231,17 +311,22 @@ static void sony_laptop_report_input_event(u8 event)
231 break; 311 break;
232 312
233 default: 313 default:
234 for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) 314 if (event > ARRAY_SIZE (sony_laptop_input_keycode_map)) {
235 if (event == sony_laptop_inputkeys[i].sonypiev) { 315 dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
316 break;
317 }
318 if (sony_laptop_input_index[event] != -1) {
319 kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]];
320 if (kp.key != KEY_UNKNOWN)
236 kp.dev = key_dev; 321 kp.dev = key_dev;
237 kp.key = sony_laptop_inputkeys[i].inputev; 322 }
238 break;
239 }
240 break; 323 break;
241 } 324 }
242 325
243 if (kp.dev) { 326 if (kp.dev) {
244 input_report_key(kp.dev, kp.key, 1); 327 input_report_key(kp.dev, kp.key, 1);
328 /* we emit the scancode so we can always remap the key */
329 input_event(kp.dev, EV_MSC, MSC_SCAN, event);
245 input_sync(kp.dev); 330 input_sync(kp.dev);
246 kfifo_put(sony_laptop_input.fifo, 331 kfifo_put(sony_laptop_input.fifo,
247 (unsigned char *)&kp, sizeof(kp)); 332 (unsigned char *)&kp, sizeof(kp));
@@ -296,11 +381,18 @@ static int sony_laptop_setup_input(void)
296 key_dev->id.vendor = PCI_VENDOR_ID_SONY; 381 key_dev->id.vendor = PCI_VENDOR_ID_SONY;
297 382
298 /* Initialize the Input Drivers: special keys */ 383 /* Initialize the Input Drivers: special keys */
299 key_dev->evbit[0] = BIT(EV_KEY); 384 set_bit(EV_KEY, key_dev->evbit);
300 for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) 385 set_bit(EV_MSC, key_dev->evbit);
301 if (sony_laptop_inputkeys[i].inputev) 386 set_bit(MSC_SCAN, key_dev->mscbit);
302 set_bit(sony_laptop_inputkeys[i].inputev, 387 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
303 key_dev->keybit); 388 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
389 key_dev->keycode = &sony_laptop_input_keycode_map;
390 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) {
391 if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) {
392 set_bit(sony_laptop_input_keycode_map[i],
393 key_dev->keybit);
394 }
395 }
304 396
305 error = input_register_device(key_dev); 397 error = input_register_device(key_dev);
306 if (error) 398 if (error)
@@ -487,6 +579,14 @@ SNC_HANDLE_NAMES(audiopower_set, "AZPW");
487SNC_HANDLE_NAMES(lanpower_get, "GLNP"); 579SNC_HANDLE_NAMES(lanpower_get, "GLNP");
488SNC_HANDLE_NAMES(lanpower_set, "LNPW"); 580SNC_HANDLE_NAMES(lanpower_set, "LNPW");
489 581
582SNC_HANDLE_NAMES(lidstate_get, "GLID");
583
584SNC_HANDLE_NAMES(indicatorlamp_get, "GILS");
585SNC_HANDLE_NAMES(indicatorlamp_set, "SILS");
586
587SNC_HANDLE_NAMES(gainbass_get, "GMGB");
588SNC_HANDLE_NAMES(gainbass_set, "CMGB");
589
490SNC_HANDLE_NAMES(PID_get, "GPID"); 590SNC_HANDLE_NAMES(PID_get, "GPID");
491 591
492SNC_HANDLE_NAMES(CTR_get, "GCTR"); 592SNC_HANDLE_NAMES(CTR_get, "GCTR");
@@ -507,6 +607,12 @@ static struct sony_nc_value sony_nc_values[] = {
507 boolean_validate, 0), 607 boolean_validate, 0),
508 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set, 608 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
509 boolean_validate, 1), 609 boolean_validate, 1),
610 SNC_HANDLE(lidstate, snc_lidstate_get, NULL,
611 boolean_validate, 0),
612 SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set,
613 boolean_validate, 0),
614 SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set,
615 boolean_validate, 0),
510 /* unknown methods */ 616 /* unknown methods */
511 SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1), 617 SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1),
512 SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), 618 SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
@@ -689,13 +795,125 @@ static struct backlight_ops sony_backlight_ops = {
689}; 795};
690 796
691/* 797/*
798 * New SNC-only Vaios event mapping to driver known keys
799 */
800struct sony_nc_event {
801 u8 data;
802 u8 event;
803};
804
805static struct sony_nc_event *sony_nc_events;
806
807/* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence
808 * for Fn keys
809 */
810static int sony_nc_C_enable(const struct dmi_system_id *id)
811{
812 int result = 0;
813
814 printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident);
815
816 sony_nc_events = id->driver_data;
817
818 if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0
819 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0
820 || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0
821 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0
822 || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0
823 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) {
824 printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some "
825 "functionalities may be missing\n");
826 return 1;
827 }
828 return 0;
829}
830
831static struct sony_nc_event sony_C_events[] = {
832 { 0x81, SONYPI_EVENT_FNKEY_F1 },
833 { 0x01, SONYPI_EVENT_FNKEY_RELEASED },
834 { 0x85, SONYPI_EVENT_FNKEY_F5 },
835 { 0x05, SONYPI_EVENT_FNKEY_RELEASED },
836 { 0x86, SONYPI_EVENT_FNKEY_F6 },
837 { 0x06, SONYPI_EVENT_FNKEY_RELEASED },
838 { 0x87, SONYPI_EVENT_FNKEY_F7 },
839 { 0x07, SONYPI_EVENT_FNKEY_RELEASED },
840 { 0x8A, SONYPI_EVENT_FNKEY_F10 },
841 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
842 { 0x8C, SONYPI_EVENT_FNKEY_F12 },
843 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
844 { 0, 0 },
845};
846
847/* SNC-only model map */
848static const struct dmi_system_id sony_nc_ids[] = {
849 {
850 .ident = "Sony Vaio FE Series",
851 .callback = sony_nc_C_enable,
852 .driver_data = sony_C_events,
853 .matches = {
854 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
855 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"),
856 },
857 },
858 {
859 .ident = "Sony Vaio FZ Series",
860 .callback = sony_nc_C_enable,
861 .driver_data = sony_C_events,
862 .matches = {
863 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
864 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"),
865 },
866 },
867 {
868 .ident = "Sony Vaio C Series",
869 .callback = sony_nc_C_enable,
870 .driver_data = sony_C_events,
871 .matches = {
872 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
873 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"),
874 },
875 },
876 { }
877};
878
879/*
692 * ACPI callbacks 880 * ACPI callbacks
693 */ 881 */
694static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) 882static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
695{ 883{
696 dprintk("sony_acpi_notify, event: %d\n", event); 884 struct sony_nc_event *evmap;
697 sony_laptop_report_input_event(event); 885 u32 ev = event;
698 acpi_bus_generate_event(sony_nc_acpi_device, 1, event); 886 int result;
887
888 if (ev == 0x92) {
889 /* read the key pressed from EC.GECR
890 * A call to SN07 with 0x0202 will do it as well respecting
891 * the current protocol on different OSes
892 *
893 * Note: the path for GECR may be
894 * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends)
895 * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR)
896 *
897 * TODO: we may want to do the same for the older GHKE -need
898 * dmi list- so this snippet may become one more callback.
899 */
900 if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0)
901 dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev);
902 else
903 ev = result & 0xFF;
904 }
905
906 if (sony_nc_events)
907 for (evmap = sony_nc_events; evmap->event; evmap++) {
908 if (evmap->data == ev) {
909 ev = evmap->event;
910 break;
911 }
912 }
913
914 dprintk("sony_acpi_notify, event: 0x%.2x\n", ev);
915 sony_laptop_report_input_event(ev);
916 acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
699} 917}
700 918
701static acpi_status sony_walk_callback(acpi_handle handle, u32 level, 919static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
@@ -732,6 +950,15 @@ static int sony_nc_resume(struct acpi_device *device)
732 break; 950 break;
733 } 951 }
734 } 952 }
953
954 /* set the last requested brightness level */
955 if (sony_backlight_device &&
956 !sony_backlight_update_status(sony_backlight_device))
957 printk(KERN_WARNING DRV_PFX "unable to restore brightness level");
958
959 /* re-initialize models with specific requirements */
960 dmi_check_system(sony_nc_ids);
961
735 return 0; 962 return 0;
736} 963}
737 964
@@ -750,6 +977,15 @@ static int sony_nc_add(struct acpi_device *device)
750 977
751 sony_nc_acpi_handle = device->handle; 978 sony_nc_acpi_handle = device->handle;
752 979
980 /* read device status */
981 result = acpi_bus_get_status(device);
982 /* bail IFF the above call was successful and the device is not present */
983 if (!result && !device->status.present) {
984 dprintk("Device not present\n");
985 result = -ENODEV;
986 goto outwalk;
987 }
988
753 if (debug) { 989 if (debug) {
754 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, 990 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
755 1, sony_walk_callback, NULL, NULL); 991 1, sony_walk_callback, NULL, NULL);
@@ -760,6 +996,15 @@ static int sony_nc_add(struct acpi_device *device)
760 } 996 }
761 } 997 }
762 998
999 /* try to _INI the device if such method exists (ACPI spec 3.0-6.5.1
1000 * should be respected as we already checked for the device presence above */
1001 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, METHOD_NAME__INI, &handle))) {
1002 dprintk("Invoking _INI\n");
1003 if (ACPI_FAILURE(acpi_evaluate_object(sony_nc_acpi_handle, METHOD_NAME__INI,
1004 NULL, NULL)))
1005 dprintk("_INI Method failed\n");
1006 }
1007
763 /* setup input devices and helper fifo */ 1008 /* setup input devices and helper fifo */
764 result = sony_laptop_setup_input(); 1009 result = sony_laptop_setup_input();
765 if (result) { 1010 if (result) {
@@ -772,7 +1017,7 @@ static int sony_nc_add(struct acpi_device *device)
772 ACPI_DEVICE_NOTIFY, 1017 ACPI_DEVICE_NOTIFY,
773 sony_acpi_notify, NULL); 1018 sony_acpi_notify, NULL);
774 if (ACPI_FAILURE(status)) { 1019 if (ACPI_FAILURE(status)) {
775 printk(KERN_WARNING DRV_PFX "unable to install notify handler\n"); 1020 printk(KERN_WARNING DRV_PFX "unable to install notify handler (%u)\n", status);
776 result = -ENODEV; 1021 result = -ENODEV;
777 goto outinput; 1022 goto outinput;
778 } 1023 }
@@ -795,6 +1040,9 @@ static int sony_nc_add(struct acpi_device *device)
795 1040
796 } 1041 }
797 1042
1043 /* initialize models with specific requirements */
1044 dmi_check_system(sony_nc_ids);
1045
798 result = sony_pf_add(); 1046 result = sony_pf_add();
799 if (result) 1047 if (result)
800 goto outbacklight; 1048 goto outbacklight;
@@ -890,10 +1138,22 @@ static int sony_nc_remove(struct acpi_device *device, int type)
890 return 0; 1138 return 0;
891} 1139}
892 1140
1141static const struct acpi_device_id sony_device_ids[] = {
1142 {SONY_NC_HID, 0},
1143 {SONY_PIC_HID, 0},
1144 {"", 0},
1145};
1146MODULE_DEVICE_TABLE(acpi, sony_device_ids);
1147
1148static const struct acpi_device_id sony_nc_device_ids[] = {
1149 {SONY_NC_HID, 0},
1150 {"", 0},
1151};
1152
893static struct acpi_driver sony_nc_driver = { 1153static struct acpi_driver sony_nc_driver = {
894 .name = SONY_NC_DRIVER_NAME, 1154 .name = SONY_NC_DRIVER_NAME,
895 .class = SONY_NC_CLASS, 1155 .class = SONY_NC_CLASS,
896 .ids = SONY_NC_HID, 1156 .ids = sony_nc_device_ids,
897 .owner = THIS_MODULE, 1157 .owner = THIS_MODULE,
898 .ops = { 1158 .ops = {
899 .add = sony_nc_add, 1159 .add = sony_nc_add,
@@ -908,7 +1168,9 @@ static struct acpi_driver sony_nc_driver = {
908#define SONYPI_DEVICE_TYPE2 0x00000002 1168#define SONYPI_DEVICE_TYPE2 0x00000002
909#define SONYPI_DEVICE_TYPE3 0x00000004 1169#define SONYPI_DEVICE_TYPE3 0x00000004
910 1170
911#define SONY_PIC_EV_MASK 0xff 1171#define SONYPI_TYPE1_OFFSET 0x04
1172#define SONYPI_TYPE2_OFFSET 0x12
1173#define SONYPI_TYPE3_OFFSET 0x12
912 1174
913struct sony_pic_ioport { 1175struct sony_pic_ioport {
914 struct acpi_resource_io io; 1176 struct acpi_resource_io io;
@@ -922,6 +1184,7 @@ struct sony_pic_irq {
922 1184
923struct sony_pic_dev { 1185struct sony_pic_dev {
924 int model; 1186 int model;
1187 u16 evport_offset;
925 u8 camera_power; 1188 u8 camera_power;
926 u8 bluetooth_power; 1189 u8 bluetooth_power;
927 u8 wwan_power; 1190 u8 wwan_power;
@@ -1999,20 +2262,17 @@ end:
1999static irqreturn_t sony_pic_irq(int irq, void *dev_id) 2262static irqreturn_t sony_pic_irq(int irq, void *dev_id)
2000{ 2263{
2001 int i, j; 2264 int i, j;
2002 u32 port_val = 0;
2003 u8 ev = 0; 2265 u8 ev = 0;
2004 u8 data_mask = 0; 2266 u8 data_mask = 0;
2005 u8 device_event = 0; 2267 u8 device_event = 0;
2006 2268
2007 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; 2269 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
2008 2270
2009 acpi_os_read_port(dev->cur_ioport->io.minimum, &port_val, 2271 ev = inb_p(dev->cur_ioport->io.minimum);
2010 dev->cur_ioport->io.address_length); 2272 data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset);
2011 ev = port_val & SONY_PIC_EV_MASK;
2012 data_mask = 0xff & (port_val >> (dev->cur_ioport->io.address_length - 8));
2013 2273
2014 dprintk("event (0x%.8x [%.2x] [%.2x]) at port 0x%.4x\n", 2274 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
2015 port_val, ev, data_mask, dev->cur_ioport->io.minimum); 2275 ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset);
2016 2276
2017 if (ev == 0x00 || ev == 0xff) 2277 if (ev == 0x00 || ev == 0xff)
2018 return IRQ_HANDLED; 2278 return IRQ_HANDLED;
@@ -2041,7 +2301,7 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
2041 2301
2042found: 2302found:
2043 sony_laptop_report_input_event(device_event); 2303 sony_laptop_report_input_event(device_event);
2044 acpi_bus_generate_event(spic_dev.acpi_dev, 1, device_event); 2304 acpi_bus_generate_proc_event(spic_dev.acpi_dev, 1, device_event);
2045 sonypi_compat_report_event(device_event); 2305 sonypi_compat_report_event(device_event);
2046 2306
2047 return IRQ_HANDLED; 2307 return IRQ_HANDLED;
@@ -2057,8 +2317,6 @@ static int sony_pic_remove(struct acpi_device *device, int type)
2057 struct sony_pic_ioport *io, *tmp_io; 2317 struct sony_pic_ioport *io, *tmp_io;
2058 struct sony_pic_irq *irq, *tmp_irq; 2318 struct sony_pic_irq *irq, *tmp_irq;
2059 2319
2060 sonypi_compat_exit();
2061
2062 if (sony_pic_disable(device)) { 2320 if (sony_pic_disable(device)) {
2063 printk(KERN_ERR DRV_PFX "Couldn't disable device.\n"); 2321 printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
2064 return -ENXIO; 2322 return -ENXIO;
@@ -2068,6 +2326,8 @@ static int sony_pic_remove(struct acpi_device *device, int type)
2068 release_region(spic_dev.cur_ioport->io.minimum, 2326 release_region(spic_dev.cur_ioport->io.minimum,
2069 spic_dev.cur_ioport->io.address_length); 2327 spic_dev.cur_ioport->io.address_length);
2070 2328
2329 sonypi_compat_exit();
2330
2071 sony_laptop_remove_input(); 2331 sony_laptop_remove_input();
2072 2332
2073 /* pf attrs */ 2333 /* pf attrs */
@@ -2103,6 +2363,20 @@ static int sony_pic_add(struct acpi_device *device)
2103 spic_dev.model = sony_pic_detect_device_type(); 2363 spic_dev.model = sony_pic_detect_device_type();
2104 mutex_init(&spic_dev.lock); 2364 mutex_init(&spic_dev.lock);
2105 2365
2366 /* model specific characteristics */
2367 switch(spic_dev.model) {
2368 case SONYPI_DEVICE_TYPE1:
2369 spic_dev.evport_offset = SONYPI_TYPE1_OFFSET;
2370 break;
2371 case SONYPI_DEVICE_TYPE3:
2372 spic_dev.evport_offset = SONYPI_TYPE3_OFFSET;
2373 break;
2374 case SONYPI_DEVICE_TYPE2:
2375 default:
2376 spic_dev.evport_offset = SONYPI_TYPE2_OFFSET;
2377 break;
2378 }
2379
2106 /* read _PRS resources */ 2380 /* read _PRS resources */
2107 result = sony_pic_possible_resources(device); 2381 result = sony_pic_possible_resources(device);
2108 if (result) { 2382 if (result) {
@@ -2119,6 +2393,9 @@ static int sony_pic_add(struct acpi_device *device)
2119 goto err_free_resources; 2393 goto err_free_resources;
2120 } 2394 }
2121 2395
2396 if (sonypi_compat_init())
2397 goto err_remove_input;
2398
2122 /* request io port */ 2399 /* request io port */
2123 list_for_each_entry(io, &spic_dev.ioports, list) { 2400 list_for_each_entry(io, &spic_dev.ioports, list) {
2124 if (request_region(io->io.minimum, io->io.address_length, 2401 if (request_region(io->io.minimum, io->io.address_length,
@@ -2133,7 +2410,7 @@ static int sony_pic_add(struct acpi_device *device)
2133 if (!spic_dev.cur_ioport) { 2410 if (!spic_dev.cur_ioport) {
2134 printk(KERN_ERR DRV_PFX "Failed to request_region.\n"); 2411 printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
2135 result = -ENODEV; 2412 result = -ENODEV;
2136 goto err_remove_input; 2413 goto err_remove_compat;
2137 } 2414 }
2138 2415
2139 /* request IRQ */ 2416 /* request IRQ */
@@ -2173,9 +2450,6 @@ static int sony_pic_add(struct acpi_device *device)
2173 if (result) 2450 if (result)
2174 goto err_remove_pf; 2451 goto err_remove_pf;
2175 2452
2176 if (sonypi_compat_init())
2177 goto err_remove_pf;
2178
2179 return 0; 2453 return 0;
2180 2454
2181err_remove_pf: 2455err_remove_pf:
@@ -2191,6 +2465,9 @@ err_release_region:
2191 release_region(spic_dev.cur_ioport->io.minimum, 2465 release_region(spic_dev.cur_ioport->io.minimum,
2192 spic_dev.cur_ioport->io.address_length); 2466 spic_dev.cur_ioport->io.address_length);
2193 2467
2468err_remove_compat:
2469 sonypi_compat_exit();
2470
2194err_remove_input: 2471err_remove_input:
2195 sony_laptop_remove_input(); 2472 sony_laptop_remove_input();
2196 2473
@@ -2222,10 +2499,15 @@ static int sony_pic_resume(struct acpi_device *device)
2222 return 0; 2499 return 0;
2223} 2500}
2224 2501
2502static const struct acpi_device_id sony_pic_device_ids[] = {
2503 {SONY_PIC_HID, 0},
2504 {"", 0},
2505};
2506
2225static struct acpi_driver sony_pic_driver = { 2507static struct acpi_driver sony_pic_driver = {
2226 .name = SONY_PIC_DRIVER_NAME, 2508 .name = SONY_PIC_DRIVER_NAME,
2227 .class = SONY_PIC_CLASS, 2509 .class = SONY_PIC_CLASS,
2228 .ids = SONY_PIC_HID, 2510 .ids = sony_pic_device_ids,
2229 .owner = THIS_MODULE, 2511 .owner = THIS_MODULE,
2230 .ops = { 2512 .ops = {
2231 .add = sony_pic_add, 2513 .add = sony_pic_add,
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 95c0b96e83f2..6c0b2f0a51ab 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -21,8 +21,8 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#define IBM_VERSION "0.14" 24#define IBM_VERSION "0.16"
25#define TPACPI_SYSFS_VERSION 0x000100 25#define TPACPI_SYSFS_VERSION 0x010000
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -92,6 +92,29 @@ MODULE_LICENSE("GPL");
92/* Please remove this in year 2009 */ 92/* Please remove this in year 2009 */
93MODULE_ALIAS("ibm_acpi"); 93MODULE_ALIAS("ibm_acpi");
94 94
95/*
96 * DMI matching for module autoloading
97 *
98 * See http://thinkwiki.org/wiki/List_of_DMI_IDs
99 * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
100 *
101 * Only models listed in thinkwiki will be supported, so add yours
102 * if it is not there yet.
103 */
104#define IBM_BIOS_MODULE_ALIAS(__type) \
105 MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW")
106
107/* Non-ancient thinkpads */
108MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
109MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
110
111/* Ancient thinkpad BIOSes have to be identified by
112 * BIOS type or model number, and there are far less
113 * BIOS types than model numbers... */
114IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]");
115IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
116IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
117
95#define __unused __attribute__ ((unused)) 118#define __unused __attribute__ ((unused))
96 119
97/**************************************************************************** 120/****************************************************************************
@@ -106,7 +129,7 @@ MODULE_ALIAS("ibm_acpi");
106 * ACPI basic handles 129 * ACPI basic handles
107 */ 130 */
108 131
109static acpi_handle root_handle = NULL; 132static acpi_handle root_handle;
110 133
111#define IBM_HANDLE(object, parent, paths...) \ 134#define IBM_HANDLE(object, parent, paths...) \
112 static acpi_handle object##_handle; \ 135 static acpi_handle object##_handle; \
@@ -388,12 +411,13 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
388 411
389 sprintf(ibm->acpi->driver->name, "%s_%s", IBM_NAME, ibm->name); 412 sprintf(ibm->acpi->driver->name, "%s_%s", IBM_NAME, ibm->name);
390 ibm->acpi->driver->ids = ibm->acpi->hid; 413 ibm->acpi->driver->ids = ibm->acpi->hid;
414
391 ibm->acpi->driver->ops.add = &tpacpi_device_add; 415 ibm->acpi->driver->ops.add = &tpacpi_device_add;
392 416
393 rc = acpi_bus_register_driver(ibm->acpi->driver); 417 rc = acpi_bus_register_driver(ibm->acpi->driver);
394 if (rc < 0) { 418 if (rc < 0) {
395 printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n", 419 printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
396 ibm->acpi->hid, rc); 420 ibm->name, rc);
397 kfree(ibm->acpi->driver); 421 kfree(ibm->acpi->driver);
398 ibm->acpi->driver = NULL; 422 ibm->acpi->driver = NULL;
399 } else if (!rc) 423 } else if (!rc)
@@ -487,19 +511,36 @@ static char *next_cmd(char **cmds)
487/**************************************************************************** 511/****************************************************************************
488 **************************************************************************** 512 ****************************************************************************
489 * 513 *
490 * Device model: hwmon and platform 514 * Device model: input, hwmon and platform
491 * 515 *
492 **************************************************************************** 516 ****************************************************************************
493 ****************************************************************************/ 517 ****************************************************************************/
494 518
495static struct platform_device *tpacpi_pdev = NULL; 519static struct platform_device *tpacpi_pdev;
496static struct class_device *tpacpi_hwmon = NULL; 520static struct class_device *tpacpi_hwmon;
521static struct input_dev *tpacpi_inputdev;
522
523
524static int tpacpi_resume_handler(struct platform_device *pdev)
525{
526 struct ibm_struct *ibm, *itmp;
527
528 list_for_each_entry_safe(ibm, itmp,
529 &tpacpi_all_drivers,
530 all_drivers) {
531 if (ibm->resume)
532 (ibm->resume)();
533 }
534
535 return 0;
536}
497 537
498static struct platform_driver tpacpi_pdriver = { 538static struct platform_driver tpacpi_pdriver = {
499 .driver = { 539 .driver = {
500 .name = IBM_DRVR_NAME, 540 .name = IBM_DRVR_NAME,
501 .owner = THIS_MODULE, 541 .owner = THIS_MODULE,
502 }, 542 },
543 .resume = tpacpi_resume_handler,
503}; 544};
504 545
505 546
@@ -677,9 +718,19 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
677 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); 718 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
678 printk(IBM_INFO "%s\n", IBM_URL); 719 printk(IBM_INFO "%s\n", IBM_URL);
679 720
680 if (ibm_thinkpad_ec_found) 721 printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n",
681 printk(IBM_INFO "ThinkPad EC firmware %s\n", 722 (thinkpad_id.bios_version_str) ?
682 ibm_thinkpad_ec_found); 723 thinkpad_id.bios_version_str : "unknown",
724 (thinkpad_id.ec_version_str) ?
725 thinkpad_id.ec_version_str : "unknown");
726
727 if (thinkpad_id.vendor && thinkpad_id.model_str)
728 printk(IBM_INFO "%s %s\n",
729 (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
730 "IBM" : ((thinkpad_id.vendor ==
731 PCI_VENDOR_ID_LENOVO) ?
732 "Lenovo" : "Unknown vendor"),
733 thinkpad_id.model_str);
683 734
684 return 0; 735 return 0;
685} 736}
@@ -704,16 +755,28 @@ static struct ibm_struct thinkpad_acpi_driver_data = {
704 */ 755 */
705 756
706static int hotkey_orig_status; 757static int hotkey_orig_status;
707static int hotkey_orig_mask; 758static u32 hotkey_orig_mask;
759static u32 hotkey_all_mask;
760static u32 hotkey_reserved_mask;
708 761
709static struct attribute_set *hotkey_dev_attributes = NULL; 762static u16 *hotkey_keycode_map;
763
764static struct attribute_set *hotkey_dev_attributes;
765
766static int hotkey_get_wlsw(int *status)
767{
768 if (!acpi_evalf(hkey_handle, status, "WLSW", "d"))
769 return -EIO;
770 return 0;
771}
710 772
711/* sysfs hotkey enable ------------------------------------------------- */ 773/* sysfs hotkey enable ------------------------------------------------- */
712static ssize_t hotkey_enable_show(struct device *dev, 774static ssize_t hotkey_enable_show(struct device *dev,
713 struct device_attribute *attr, 775 struct device_attribute *attr,
714 char *buf) 776 char *buf)
715{ 777{
716 int res, status, mask; 778 int res, status;
779 u32 mask;
717 780
718 res = hotkey_get(&status, &mask); 781 res = hotkey_get(&status, &mask);
719 if (res) 782 if (res)
@@ -727,7 +790,8 @@ static ssize_t hotkey_enable_store(struct device *dev,
727 const char *buf, size_t count) 790 const char *buf, size_t count)
728{ 791{
729 unsigned long t; 792 unsigned long t;
730 int res, status, mask; 793 int res, status;
794 u32 mask;
731 795
732 if (parse_strtoul(buf, 1, &t)) 796 if (parse_strtoul(buf, 1, &t))
733 return -EINVAL; 797 return -EINVAL;
@@ -748,13 +812,14 @@ static ssize_t hotkey_mask_show(struct device *dev,
748 struct device_attribute *attr, 812 struct device_attribute *attr,
749 char *buf) 813 char *buf)
750{ 814{
751 int res, status, mask; 815 int res, status;
816 u32 mask;
752 817
753 res = hotkey_get(&status, &mask); 818 res = hotkey_get(&status, &mask);
754 if (res) 819 if (res)
755 return res; 820 return res;
756 821
757 return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask); 822 return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask);
758} 823}
759 824
760static ssize_t hotkey_mask_store(struct device *dev, 825static ssize_t hotkey_mask_store(struct device *dev,
@@ -762,9 +827,10 @@ static ssize_t hotkey_mask_store(struct device *dev,
762 const char *buf, size_t count) 827 const char *buf, size_t count)
763{ 828{
764 unsigned long t; 829 unsigned long t;
765 int res, status, mask; 830 int res, status;
831 u32 mask;
766 832
767 if (parse_strtoul(buf, 0xffff, &t)) 833 if (parse_strtoul(buf, 0xffffffffUL, &t))
768 return -EINVAL; 834 return -EINVAL;
769 835
770 res = hotkey_get(&status, &mask); 836 res = hotkey_get(&status, &mask);
@@ -794,26 +860,140 @@ static ssize_t hotkey_bios_mask_show(struct device *dev,
794 struct device_attribute *attr, 860 struct device_attribute *attr,
795 char *buf) 861 char *buf)
796{ 862{
797 return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask); 863 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask);
798} 864}
799 865
800static struct device_attribute dev_attr_hotkey_bios_mask = 866static struct device_attribute dev_attr_hotkey_bios_mask =
801 __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); 867 __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
802 868
869/* sysfs hotkey all_mask ----------------------------------------------- */
870static ssize_t hotkey_all_mask_show(struct device *dev,
871 struct device_attribute *attr,
872 char *buf)
873{
874 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask);
875}
876
877static struct device_attribute dev_attr_hotkey_all_mask =
878 __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL);
879
880/* sysfs hotkey recommended_mask --------------------------------------- */
881static ssize_t hotkey_recommended_mask_show(struct device *dev,
882 struct device_attribute *attr,
883 char *buf)
884{
885 return snprintf(buf, PAGE_SIZE, "0x%08x\n",
886 hotkey_all_mask & ~hotkey_reserved_mask);
887}
888
889static struct device_attribute dev_attr_hotkey_recommended_mask =
890 __ATTR(hotkey_recommended_mask, S_IRUGO,
891 hotkey_recommended_mask_show, NULL);
892
893/* sysfs hotkey radio_sw ----------------------------------------------- */
894static ssize_t hotkey_radio_sw_show(struct device *dev,
895 struct device_attribute *attr,
896 char *buf)
897{
898 int res, s;
899 res = hotkey_get_wlsw(&s);
900 if (res < 0)
901 return res;
902
903 return snprintf(buf, PAGE_SIZE, "%d\n", !!s);
904}
905
906static struct device_attribute dev_attr_hotkey_radio_sw =
907 __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);
908
909/* sysfs hotkey report_mode -------------------------------------------- */
910static ssize_t hotkey_report_mode_show(struct device *dev,
911 struct device_attribute *attr,
912 char *buf)
913{
914 return snprintf(buf, PAGE_SIZE, "%d\n",
915 (hotkey_report_mode != 0) ? hotkey_report_mode : 1);
916}
917
918static struct device_attribute dev_attr_hotkey_report_mode =
919 __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
920
803/* --------------------------------------------------------------------- */ 921/* --------------------------------------------------------------------- */
804 922
805static struct attribute *hotkey_mask_attributes[] = { 923static struct attribute *hotkey_attributes[] __initdata = {
924 &dev_attr_hotkey_enable.attr,
925 &dev_attr_hotkey_report_mode.attr,
926};
927
928static struct attribute *hotkey_mask_attributes[] __initdata = {
806 &dev_attr_hotkey_mask.attr, 929 &dev_attr_hotkey_mask.attr,
807 &dev_attr_hotkey_bios_enabled.attr, 930 &dev_attr_hotkey_bios_enabled.attr,
808 &dev_attr_hotkey_bios_mask.attr, 931 &dev_attr_hotkey_bios_mask.attr,
932 &dev_attr_hotkey_all_mask.attr,
933 &dev_attr_hotkey_recommended_mask.attr,
809}; 934};
810 935
811static int __init hotkey_init(struct ibm_init_struct *iibm) 936static int __init hotkey_init(struct ibm_init_struct *iibm)
812{ 937{
813 int res; 938
939 static u16 ibm_keycode_map[] __initdata = {
940 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
941 KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP,
942 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
943 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
944 /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
945 KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
946 KEY_UNKNOWN, /* 0x0D: FN+INSERT */
947 KEY_UNKNOWN, /* 0x0E: FN+DELETE */
948 KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
949 /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
950 KEY_RESERVED, /* 0x10: FN+END (brightness down) */
951 KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
952 KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
953 KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
954 KEY_RESERVED, /* 0x14: VOLUME UP */
955 KEY_RESERVED, /* 0x15: VOLUME DOWN */
956 KEY_RESERVED, /* 0x16: MUTE */
957 KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
958 /* (assignments unknown, please report if found) */
959 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
960 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
961 };
962 static u16 lenovo_keycode_map[] __initdata = {
963 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
964 KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP,
965 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
966 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
967 /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
968 KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
969 KEY_UNKNOWN, /* 0x0D: FN+INSERT */
970 KEY_UNKNOWN, /* 0x0E: FN+DELETE */
971 KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */
972 /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
973 KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */
974 KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
975 KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
976 KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
977 KEY_RESERVED, /* 0x14: VOLUME UP */
978 KEY_RESERVED, /* 0x15: VOLUME DOWN */
979 KEY_RESERVED, /* 0x16: MUTE */
980 KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
981 /* (assignments unknown, please report if found) */
982 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
983 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
984 };
985
986#define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map)
987#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map)
988#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0])
989
990 int res, i;
991 int status;
814 992
815 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 993 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
816 994
995 BUG_ON(!tpacpi_inputdev);
996
817 IBM_ACPIHANDLE_INIT(hkey); 997 IBM_ACPIHANDLE_INIT(hkey);
818 mutex_init(&hotkey_mutex); 998 mutex_init(&hotkey_mutex);
819 999
@@ -824,11 +1004,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
824 str_supported(tp_features.hotkey)); 1004 str_supported(tp_features.hotkey));
825 1005
826 if (tp_features.hotkey) { 1006 if (tp_features.hotkey) {
827 hotkey_dev_attributes = create_attr_set(4, NULL); 1007 hotkey_dev_attributes = create_attr_set(8, NULL);
828 if (!hotkey_dev_attributes) 1008 if (!hotkey_dev_attributes)
829 return -ENOMEM; 1009 return -ENOMEM;
830 res = add_to_attr_set(hotkey_dev_attributes, 1010 res = add_many_to_attr_set(hotkey_dev_attributes,
831 &dev_attr_hotkey_enable.attr); 1011 hotkey_attributes,
1012 ARRAY_SIZE(hotkey_attributes));
832 if (res) 1013 if (res)
833 return res; 1014 return res;
834 1015
@@ -840,19 +1021,90 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
840 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", 1021 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
841 str_supported(tp_features.hotkey_mask)); 1022 str_supported(tp_features.hotkey_mask));
842 1023
1024 if (tp_features.hotkey_mask) {
1025 /* MHKA available in A31, R40, R40e, T4x, X31, and later */
1026 if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
1027 "MHKA", "qd"))
1028 hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */
1029 }
1030
843 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); 1031 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
844 if (!res && tp_features.hotkey_mask) { 1032 if (!res && tp_features.hotkey_mask) {
845 res = add_many_to_attr_set(hotkey_dev_attributes, 1033 res = add_many_to_attr_set(hotkey_dev_attributes,
846 hotkey_mask_attributes, 1034 hotkey_mask_attributes,
847 ARRAY_SIZE(hotkey_mask_attributes)); 1035 ARRAY_SIZE(hotkey_mask_attributes));
848 } 1036 }
1037
1038 /* Not all thinkpads have a hardware radio switch */
1039 if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
1040 tp_features.hotkey_wlsw = 1;
1041 printk(IBM_INFO
1042 "radio switch found; radios are %s\n",
1043 enabled(status, 0));
1044 res = add_to_attr_set(hotkey_dev_attributes,
1045 &dev_attr_hotkey_radio_sw.attr);
1046 }
1047
849 if (!res) 1048 if (!res)
850 res = register_attr_set_with_sysfs( 1049 res = register_attr_set_with_sysfs(
851 hotkey_dev_attributes, 1050 hotkey_dev_attributes,
852 &tpacpi_pdev->dev.kobj); 1051 &tpacpi_pdev->dev.kobj);
1052 if (res)
1053 return res;
1054
1055 /* Set up key map */
1056
1057 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
1058 GFP_KERNEL);
1059 if (!hotkey_keycode_map) {
1060 printk(IBM_ERR "failed to allocate memory for key map\n");
1061 return -ENOMEM;
1062 }
853 1063
1064 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
1065 dbg_printk(TPACPI_DBG_INIT,
1066 "using Lenovo default hot key map\n");
1067 memcpy(hotkey_keycode_map, &lenovo_keycode_map,
1068 TPACPI_HOTKEY_MAP_SIZE);
1069 } else {
1070 dbg_printk(TPACPI_DBG_INIT,
1071 "using IBM default hot key map\n");
1072 memcpy(hotkey_keycode_map, &ibm_keycode_map,
1073 TPACPI_HOTKEY_MAP_SIZE);
1074 }
1075
1076 set_bit(EV_KEY, tpacpi_inputdev->evbit);
1077 set_bit(EV_MSC, tpacpi_inputdev->evbit);
1078 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
1079 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
1080 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
1081 tpacpi_inputdev->keycode = hotkey_keycode_map;
1082 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
1083 if (hotkey_keycode_map[i] != KEY_RESERVED) {
1084 set_bit(hotkey_keycode_map[i],
1085 tpacpi_inputdev->keybit);
1086 } else {
1087 if (i < sizeof(hotkey_reserved_mask)*8)
1088 hotkey_reserved_mask |= 1 << i;
1089 }
1090 }
1091
1092 if (tp_features.hotkey_wlsw) {
1093 set_bit(EV_SW, tpacpi_inputdev->evbit);
1094 set_bit(SW_RADIO, tpacpi_inputdev->swbit);
1095 }
1096
1097 dbg_printk(TPACPI_DBG_INIT,
1098 "enabling hot key handling\n");
1099 res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)
1100 | hotkey_orig_mask);
854 if (res) 1101 if (res)
855 return res; 1102 return res;
1103
1104 dbg_printk(TPACPI_DBG_INIT,
1105 "legacy hot key reporting over procfs %s\n",
1106 (hotkey_report_mode < 2) ?
1107 "enabled" : "disabled");
856 } 1108 }
857 1109
858 return (tp_features.hotkey)? 0 : 1; 1110 return (tp_features.hotkey)? 0 : 1;
@@ -875,22 +1127,108 @@ static void hotkey_exit(void)
875 } 1127 }
876} 1128}
877 1129
1130static void tpacpi_input_send_key(unsigned int scancode,
1131 unsigned int keycode)
1132{
1133 if (keycode != KEY_RESERVED) {
1134 input_report_key(tpacpi_inputdev, keycode, 1);
1135 if (keycode == KEY_UNKNOWN)
1136 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1137 scancode);
1138 input_sync(tpacpi_inputdev);
1139
1140 input_report_key(tpacpi_inputdev, keycode, 0);
1141 if (keycode == KEY_UNKNOWN)
1142 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1143 scancode);
1144 input_sync(tpacpi_inputdev);
1145 }
1146}
1147
1148static void tpacpi_input_send_radiosw(void)
1149{
1150 int wlsw;
1151
1152 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw))
1153 input_report_switch(tpacpi_inputdev,
1154 SW_RADIO, !!wlsw);
1155}
1156
878static void hotkey_notify(struct ibm_struct *ibm, u32 event) 1157static void hotkey_notify(struct ibm_struct *ibm, u32 event)
879{ 1158{
880 int hkey; 1159 u32 hkey;
1160 unsigned int keycode, scancode;
1161 int send_acpi_ev = 0;
1162
1163 if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
1164 switch (hkey >> 12) {
1165 case 1:
1166 /* 0x1000-0x1FFF: key presses */
1167 scancode = hkey & 0xfff;
1168 if (scancode > 0 && scancode < 0x21) {
1169 scancode--;
1170 keycode = hotkey_keycode_map[scancode];
1171 tpacpi_input_send_key(scancode, keycode);
1172 } else {
1173 printk(IBM_ERR
1174 "hotkey 0x%04x out of range for keyboard map\n",
1175 hkey);
1176 send_acpi_ev = 1;
1177 }
1178 break;
1179 case 5:
1180 /* 0x5000-0x5FFF: LID */
1181 /* we don't handle it through this path, just
1182 * eat up known LID events */
1183 if (hkey != 0x5001 && hkey != 0x5002) {
1184 printk(IBM_ERR
1185 "unknown LID-related hotkey event: 0x%04x\n",
1186 hkey);
1187 send_acpi_ev = 1;
1188 }
1189 break;
1190 case 7:
1191 /* 0x7000-0x7FFF: misc */
1192 if (tp_features.hotkey_wlsw && hkey == 0x7000) {
1193 tpacpi_input_send_radiosw();
1194 break;
1195 }
1196 /* fallthrough to default */
1197 default:
1198 /* case 2: dock-related */
1199 /* 0x2305 - T43 waking up due to bay lever eject while aslept */
1200 /* case 3: ultra-bay related. maybe bay in dock? */
1201 /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */
1202 printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
1203 send_acpi_ev = 1;
1204 }
1205 } else {
1206 printk(IBM_ERR "unknown hotkey notification event %d\n", event);
1207 hkey = 0;
1208 send_acpi_ev = 1;
1209 }
881 1210
882 if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) 1211 /* Legacy events */
883 acpi_bus_generate_event(ibm->acpi->device, event, hkey); 1212 if (send_acpi_ev || hotkey_report_mode < 2)
884 else { 1213 acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
885 printk(IBM_ERR "unknown hotkey event %d\n", event); 1214
886 acpi_bus_generate_event(ibm->acpi->device, event, 0); 1215 /* netlink events */
1216 if (send_acpi_ev) {
1217 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
1218 ibm->acpi->device->dev.bus_id,
1219 event, hkey);
887 } 1220 }
888} 1221}
889 1222
1223static void hotkey_resume(void)
1224{
1225 tpacpi_input_send_radiosw();
1226}
1227
890/* 1228/*
891 * Call with hotkey_mutex held 1229 * Call with hotkey_mutex held
892 */ 1230 */
893static int hotkey_get(int *status, int *mask) 1231static int hotkey_get(int *status, u32 *mask)
894{ 1232{
895 if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) 1233 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
896 return -EIO; 1234 return -EIO;
@@ -905,7 +1243,7 @@ static int hotkey_get(int *status, int *mask)
905/* 1243/*
906 * Call with hotkey_mutex held 1244 * Call with hotkey_mutex held
907 */ 1245 */
908static int hotkey_set(int status, int mask) 1246static int hotkey_set(int status, u32 mask)
909{ 1247{
910 int i; 1248 int i;
911 1249
@@ -926,7 +1264,8 @@ static int hotkey_set(int status, int mask)
926/* procfs -------------------------------------------------------------- */ 1264/* procfs -------------------------------------------------------------- */
927static int hotkey_read(char *p) 1265static int hotkey_read(char *p)
928{ 1266{
929 int res, status, mask; 1267 int res, status;
1268 u32 mask;
930 int len = 0; 1269 int len = 0;
931 1270
932 if (!tp_features.hotkey) { 1271 if (!tp_features.hotkey) {
@@ -944,7 +1283,7 @@ static int hotkey_read(char *p)
944 1283
945 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); 1284 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
946 if (tp_features.hotkey_mask) { 1285 if (tp_features.hotkey_mask) {
947 len += sprintf(p + len, "mask:\t\t0x%04x\n", mask); 1286 len += sprintf(p + len, "mask:\t\t0x%08x\n", mask);
948 len += sprintf(p + len, 1287 len += sprintf(p + len,
949 "commands:\tenable, disable, reset, <mask>\n"); 1288 "commands:\tenable, disable, reset, <mask>\n");
950 } else { 1289 } else {
@@ -957,7 +1296,8 @@ static int hotkey_read(char *p)
957 1296
958static int hotkey_write(char *buf) 1297static int hotkey_write(char *buf)
959{ 1298{
960 int res, status, mask; 1299 int res, status;
1300 u32 mask;
961 char *cmd; 1301 char *cmd;
962 int do_cmd = 0; 1302 int do_cmd = 0;
963 1303
@@ -1000,8 +1340,13 @@ errexit:
1000 return res; 1340 return res;
1001} 1341}
1002 1342
1343static const struct acpi_device_id ibm_htk_device_ids[] = {
1344 {IBM_HKEY_HID, 0},
1345 {"", 0},
1346};
1347
1003static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = { 1348static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = {
1004 .hid = IBM_HKEY_HID, 1349 .hid = ibm_htk_device_ids,
1005 .notify = hotkey_notify, 1350 .notify = hotkey_notify,
1006 .handle = &hkey_handle, 1351 .handle = &hkey_handle,
1007 .type = ACPI_DEVICE_NOTIFY, 1352 .type = ACPI_DEVICE_NOTIFY,
@@ -1012,6 +1357,7 @@ static struct ibm_struct hotkey_driver_data = {
1012 .read = hotkey_read, 1357 .read = hotkey_read,
1013 .write = hotkey_write, 1358 .write = hotkey_write,
1014 .exit = hotkey_exit, 1359 .exit = hotkey_exit,
1360 .resume = hotkey_resume,
1015 .acpi = &ibm_hotkey_acpidriver, 1361 .acpi = &ibm_hotkey_acpidriver,
1016}; 1362};
1017 1363
@@ -1763,6 +2109,11 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
1763/* don't list other alternatives as we install a notify handler on the 570 */ 2109/* don't list other alternatives as we install a notify handler on the 570 */
1764IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ 2110IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
1765 2111
2112static const struct acpi_device_id ibm_pci_device_ids[] = {
2113 {PCI_ROOT_HID_STRING, 0},
2114 {"", 0},
2115};
2116
1766static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = { 2117static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = {
1767 { 2118 {
1768 .notify = dock_notify, 2119 .notify = dock_notify,
@@ -1770,7 +2121,10 @@ static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = {
1770 .type = ACPI_SYSTEM_NOTIFY, 2121 .type = ACPI_SYSTEM_NOTIFY,
1771 }, 2122 },
1772 { 2123 {
1773 .hid = IBM_PCI_HID, 2124 /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING.
2125 * We just use it to get notifications of dock hotplug
2126 * in very old thinkpads */
2127 .hid = ibm_pci_device_ids,
1774 .notify = dock_notify, 2128 .notify = dock_notify,
1775 .handle = &pci_handle, 2129 .handle = &pci_handle,
1776 .type = ACPI_SYSTEM_NOTIFY, 2130 .type = ACPI_SYSTEM_NOTIFY,
@@ -1829,23 +2183,29 @@ static int __init dock_init2(struct ibm_init_struct *iibm)
1829static void dock_notify(struct ibm_struct *ibm, u32 event) 2183static void dock_notify(struct ibm_struct *ibm, u32 event)
1830{ 2184{
1831 int docked = dock_docked(); 2185 int docked = dock_docked();
1832 int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, IBM_PCI_HID); 2186 int pci = ibm->acpi->hid && ibm->acpi->device &&
2187 acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids);
2188 int data;
1833 2189
1834 if (event == 1 && !pci) /* 570 */ 2190 if (event == 1 && !pci) /* 570 */
1835 acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ 2191 data = 1; /* button */
1836 else if (event == 1 && pci) /* 570 */ 2192 else if (event == 1 && pci) /* 570 */
1837 acpi_bus_generate_event(ibm->acpi->device, event, 3); /* dock */ 2193 data = 3; /* dock */
1838 else if (event == 3 && docked) 2194 else if (event == 3 && docked)
1839 acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ 2195 data = 1; /* button */
1840 else if (event == 3 && !docked) 2196 else if (event == 3 && !docked)
1841 acpi_bus_generate_event(ibm->acpi->device, event, 2); /* undock */ 2197 data = 2; /* undock */
1842 else if (event == 0 && docked) 2198 else if (event == 0 && docked)
1843 acpi_bus_generate_event(ibm->acpi->device, event, 3); /* dock */ 2199 data = 3; /* dock */
1844 else { 2200 else {
1845 printk(IBM_ERR "unknown dock event %d, status %d\n", 2201 printk(IBM_ERR "unknown dock event %d, status %d\n",
1846 event, _sta(dock_handle)); 2202 event, _sta(dock_handle));
1847 acpi_bus_generate_event(ibm->acpi->device, event, 0); /* unknown */ 2203 data = 0; /* unknown */
1848 } 2204 }
2205 acpi_bus_generate_proc_event(ibm->acpi->device, event, data);
2206 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
2207 ibm->acpi->device->dev.bus_id,
2208 event, data);
1849} 2209}
1850 2210
1851static int dock_read(char *p) 2211static int dock_read(char *p)
@@ -1943,7 +2303,10 @@ static int __init bay_init(struct ibm_init_struct *iibm)
1943 2303
1944static void bay_notify(struct ibm_struct *ibm, u32 event) 2304static void bay_notify(struct ibm_struct *ibm, u32 event)
1945{ 2305{
1946 acpi_bus_generate_event(ibm->acpi->device, event, 0); 2306 acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
2307 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
2308 ibm->acpi->device->dev.bus_id,
2309 event, 0);
1947} 2310}
1948 2311
1949#define bay_occupied(b) (_sta(b##_handle) & 1) 2312#define bay_occupied(b) (_sta(b##_handle) & 1)
@@ -2389,7 +2752,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
2389 2752
2390 acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); 2753 acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
2391 2754
2392 if (ibm_thinkpad_ec_found && experimental) { 2755 if (thinkpad_id.ec_model) {
2393 /* 2756 /*
2394 * Direct EC access mode: sensors at registers 2757 * Direct EC access mode: sensors at registers
2395 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for 2758 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for
@@ -2533,6 +2896,8 @@ static int thermal_get_sensor(int idx, s32 *value)
2533 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); 2896 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
2534 if (!acpi_evalf(ec_handle, &t, tmpi, "d")) 2897 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
2535 return -EIO; 2898 return -EIO;
2899 if (t > 127 || t < -127)
2900 t = TP_EC_THERMAL_TMP_NA;
2536 *value = t * 1000; 2901 *value = t * 1000;
2537 return 0; 2902 return 0;
2538 } 2903 }
@@ -2671,22 +3036,39 @@ static struct ibm_struct ecdump_driver_data = {
2671 * Backlight/brightness subdriver 3036 * Backlight/brightness subdriver
2672 */ 3037 */
2673 3038
2674static struct backlight_device *ibm_backlight_device = NULL; 3039static struct backlight_device *ibm_backlight_device;
2675 3040
2676static struct backlight_ops ibm_backlight_data = { 3041static struct backlight_ops ibm_backlight_data = {
2677 .get_brightness = brightness_get, 3042 .get_brightness = brightness_get,
2678 .update_status = brightness_update_status, 3043 .update_status = brightness_update_status,
2679}; 3044};
2680 3045
3046static struct mutex brightness_mutex;
3047
2681static int __init brightness_init(struct ibm_init_struct *iibm) 3048static int __init brightness_init(struct ibm_init_struct *iibm)
2682{ 3049{
2683 int b; 3050 int b;
2684 3051
2685 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); 3052 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n");
2686 3053
3054 mutex_init(&brightness_mutex);
3055
3056 if (!brightness_mode) {
3057 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO)
3058 brightness_mode = 2;
3059 else
3060 brightness_mode = 3;
3061
3062 dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n",
3063 brightness_mode);
3064 }
3065
3066 if (brightness_mode > 3)
3067 return -EINVAL;
3068
2687 b = brightness_get(NULL); 3069 b = brightness_get(NULL);
2688 if (b < 0) 3070 if (b < 0)
2689 return b; 3071 return 1;
2690 3072
2691 ibm_backlight_device = backlight_device_register( 3073 ibm_backlight_device = backlight_device_register(
2692 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, 3074 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
@@ -2722,34 +3104,79 @@ static int brightness_update_status(struct backlight_device *bd)
2722 bd->props.brightness : 0); 3104 bd->props.brightness : 0);
2723} 3105}
2724 3106
3107/*
3108 * ThinkPads can read brightness from two places: EC 0x31, or
3109 * CMOS NVRAM byte 0x5E, bits 0-3.
3110 */
2725static int brightness_get(struct backlight_device *bd) 3111static int brightness_get(struct backlight_device *bd)
2726{ 3112{
2727 u8 level; 3113 u8 lec = 0, lcmos = 0, level = 0;
2728 if (!acpi_ec_read(brightness_offset, &level)) 3114
2729 return -EIO; 3115 if (brightness_mode & 1) {
3116 if (!acpi_ec_read(brightness_offset, &lec))
3117 return -EIO;
3118 lec &= 7;
3119 level = lec;
3120 };
3121 if (brightness_mode & 2) {
3122 lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
3123 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
3124 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
3125 level = lcmos;
3126 }
2730 3127
2731 level &= 0x7; 3128 if (brightness_mode == 3 && lec != lcmos) {
3129 printk(IBM_ERR
3130 "CMOS NVRAM (%u) and EC (%u) do not agree "
3131 "on display brightness level\n",
3132 (unsigned int) lcmos,
3133 (unsigned int) lec);
3134 return -EIO;
3135 }
2732 3136
2733 return level; 3137 return level;
2734} 3138}
2735 3139
2736static int brightness_set(int value) 3140static int brightness_set(int value)
2737{ 3141{
2738 int cmos_cmd, inc, i; 3142 int cmos_cmd, inc, i, res;
2739 int current_value = brightness_get(NULL); 3143 int current_value;
3144
3145 if (value > 7)
3146 return -EINVAL;
2740 3147
2741 value &= 7; 3148 res = mutex_lock_interruptible(&brightness_mutex);
3149 if (res < 0)
3150 return res;
2742 3151
2743 cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN; 3152 current_value = brightness_get(NULL);
3153 if (current_value < 0) {
3154 res = current_value;
3155 goto errout;
3156 }
3157
3158 cmos_cmd = value > current_value ?
3159 TP_CMOS_BRIGHTNESS_UP :
3160 TP_CMOS_BRIGHTNESS_DOWN;
2744 inc = value > current_value ? 1 : -1; 3161 inc = value > current_value ? 1 : -1;
3162
3163 res = 0;
2745 for (i = current_value; i != value; i += inc) { 3164 for (i = current_value; i != value; i += inc) {
2746 if (issue_thinkpad_cmos_command(cmos_cmd)) 3165 if ((brightness_mode & 2) &&
2747 return -EIO; 3166 issue_thinkpad_cmos_command(cmos_cmd)) {
2748 if (!acpi_ec_write(brightness_offset, i + inc)) 3167 res = -EIO;
2749 return -EIO; 3168 goto errout;
3169 }
3170 if ((brightness_mode & 1) &&
3171 !acpi_ec_write(brightness_offset, i + inc)) {
3172 res = -EIO;
3173 goto errout;;
3174 }
2750 } 3175 }
2751 3176
2752 return 0; 3177errout:
3178 mutex_unlock(&brightness_mutex);
3179 return res;
2753} 3180}
2754 3181
2755static int brightness_read(char *p) 3182static int brightness_read(char *p)
@@ -3273,20 +3700,19 @@ static int __init fan_init(struct ibm_init_struct *iibm)
3273 * Enable for TP-1Y (T43), TP-78 (R51e), 3700 * Enable for TP-1Y (T43), TP-78 (R51e),
3274 * TP-76 (R52), TP-70 (T43, R52), which are known 3701 * TP-76 (R52), TP-70 (T43, R52), which are known
3275 * to be buggy. */ 3702 * to be buggy. */
3276 if (fan_control_initial_status == 0x07 && 3703 if (fan_control_initial_status == 0x07) {
3277 ibm_thinkpad_ec_found && 3704 switch (thinkpad_id.ec_model) {
3278 ((ibm_thinkpad_ec_found[0] == '1' && 3705 case 0x5931: /* TP-1Y */
3279 ibm_thinkpad_ec_found[1] == 'Y') || 3706 case 0x3837: /* TP-78 */
3280 (ibm_thinkpad_ec_found[0] == '7' && 3707 case 0x3637: /* TP-76 */
3281 (ibm_thinkpad_ec_found[1] == '6' || 3708 case 0x3037: /* TP-70 */
3282 ibm_thinkpad_ec_found[1] == '8' || 3709 printk(IBM_NOTICE
3283 ibm_thinkpad_ec_found[1] == '0')) 3710 "fan_init: initial fan status is "
3284 )) { 3711 "unknown, assuming it is in auto "
3285 printk(IBM_NOTICE 3712 "mode\n");
3286 "fan_init: initial fan status is " 3713 tp_features.fan_ctrl_status_undef = 1;
3287 "unknown, assuming it is in auto " 3714 ;;
3288 "mode\n"); 3715 }
3289 tp_features.fan_ctrl_status_undef = 1;
3290 } 3716 }
3291 } else { 3717 } else {
3292 printk(IBM_ERR 3718 printk(IBM_ERR
@@ -3474,7 +3900,7 @@ static void fan_watchdog_fire(struct work_struct *ignored)
3474 3900
3475static void fan_watchdog_reset(void) 3901static void fan_watchdog_reset(void)
3476{ 3902{
3477 static int fan_watchdog_active = 0; 3903 static int fan_watchdog_active;
3478 3904
3479 if (fan_control_access_mode == TPACPI_FAN_WR_NONE) 3905 if (fan_control_access_mode == TPACPI_FAN_WR_NONE)
3480 return; 3906 return;
@@ -3877,7 +4303,7 @@ static struct ibm_struct fan_driver_data = {
3877 ****************************************************************************/ 4303 ****************************************************************************/
3878 4304
3879/* /proc support */ 4305/* /proc support */
3880static struct proc_dir_entry *proc_dir = NULL; 4306static struct proc_dir_entry *proc_dir;
3881 4307
3882/* Subdriver registry */ 4308/* Subdriver registry */
3883static LIST_HEAD(tpacpi_all_drivers); 4309static LIST_HEAD(tpacpi_all_drivers);
@@ -4020,13 +4446,30 @@ static void ibm_exit(struct ibm_struct *ibm)
4020 4446
4021/* Probing */ 4447/* Probing */
4022 4448
4023static char *ibm_thinkpad_ec_found = NULL; 4449static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
4024
4025static char* __init check_dmi_for_ec(void)
4026{ 4450{
4027 struct dmi_device *dev = NULL; 4451 const struct dmi_device *dev = NULL;
4028 char ec_fw_string[18]; 4452 char ec_fw_string[18];
4029 4453
4454 if (!tp)
4455 return;
4456
4457 memset(tp, 0, sizeof(*tp));
4458
4459 if (dmi_name_in_vendors("IBM"))
4460 tp->vendor = PCI_VENDOR_ID_IBM;
4461 else if (dmi_name_in_vendors("LENOVO"))
4462 tp->vendor = PCI_VENDOR_ID_LENOVO;
4463 else
4464 return;
4465
4466 tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION),
4467 GFP_KERNEL);
4468 if (!tp->bios_version_str)
4469 return;
4470 tp->bios_model = tp->bios_version_str[0]
4471 | (tp->bios_version_str[1] << 8);
4472
4030 /* 4473 /*
4031 * ThinkPad T23 or newer, A31 or newer, R50e or newer, 4474 * ThinkPad T23 or newer, A31 or newer, R50e or newer,
4032 * X32 or newer, all Z series; Some models must have an 4475 * X32 or newer, all Z series; Some models must have an
@@ -4040,10 +4483,20 @@ static char* __init check_dmi_for_ec(void)
4040 ec_fw_string) == 1) { 4483 ec_fw_string) == 1) {
4041 ec_fw_string[sizeof(ec_fw_string) - 1] = 0; 4484 ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
4042 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; 4485 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
4043 return kstrdup(ec_fw_string, GFP_KERNEL); 4486
4487 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
4488 tp->ec_model = ec_fw_string[0]
4489 | (ec_fw_string[1] << 8);
4490 break;
4044 } 4491 }
4045 } 4492 }
4046 return NULL; 4493
4494 tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION),
4495 GFP_KERNEL);
4496 if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
4497 kfree(tp->model_str);
4498 tp->model_str = NULL;
4499 }
4047} 4500}
4048 4501
4049static int __init probe_for_thinkpad(void) 4502static int __init probe_for_thinkpad(void)
@@ -4057,7 +4510,7 @@ static int __init probe_for_thinkpad(void)
4057 * Non-ancient models have better DMI tagging, but very old models 4510 * Non-ancient models have better DMI tagging, but very old models
4058 * don't. 4511 * don't.
4059 */ 4512 */
4060 is_thinkpad = dmi_name_in_vendors("ThinkPad"); 4513 is_thinkpad = (thinkpad_id.model_str != NULL);
4061 4514
4062 /* ec is required because many other handles are relative to it */ 4515 /* ec is required because many other handles are relative to it */
4063 IBM_ACPIHANDLE_INIT(ec); 4516 IBM_ACPIHANDLE_INIT(ec);
@@ -4073,7 +4526,7 @@ static int __init probe_for_thinkpad(void)
4073 * false positives a damn great deal 4526 * false positives a damn great deal
4074 */ 4527 */
4075 if (!is_thinkpad) 4528 if (!is_thinkpad)
4076 is_thinkpad = dmi_name_in_vendors("IBM"); 4529 is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM);
4077 4530
4078 if (!is_thinkpad && !force_load) 4531 if (!is_thinkpad && !force_load)
4079 return -ENODEV; 4532 return -ENODEV;
@@ -4185,10 +4638,16 @@ static u32 dbg_level;
4185module_param_named(debug, dbg_level, uint, 0); 4638module_param_named(debug, dbg_level, uint, 0);
4186 4639
4187static int force_load; 4640static int force_load;
4188module_param(force_load, int, 0); 4641module_param(force_load, bool, 0);
4189 4642
4190static int fan_control_allowed; 4643static int fan_control_allowed;
4191module_param_named(fan_control, fan_control_allowed, int, 0); 4644module_param_named(fan_control, fan_control_allowed, bool, 0);
4645
4646static int brightness_mode;
4647module_param_named(brightness_mode, brightness_mode, int, 0);
4648
4649static unsigned int hotkey_report_mode;
4650module_param(hotkey_report_mode, uint, 0);
4192 4651
4193#define IBM_PARAM(feature) \ 4652#define IBM_PARAM(feature) \
4194 module_param_call(feature, set_ibm_param, NULL, NULL, 0) 4653 module_param_call(feature, set_ibm_param, NULL, NULL, 0)
@@ -4215,13 +4674,21 @@ static int __init thinkpad_acpi_module_init(void)
4215{ 4674{
4216 int ret, i; 4675 int ret, i;
4217 4676
4677 /* Parameter checking */
4678 if (hotkey_report_mode > 2)
4679 return -EINVAL;
4680
4218 /* Driver-level probe */ 4681 /* Driver-level probe */
4682
4683 get_thinkpad_model_data(&thinkpad_id);
4219 ret = probe_for_thinkpad(); 4684 ret = probe_for_thinkpad();
4220 if (ret) 4685 if (ret) {
4686 thinkpad_acpi_module_exit();
4221 return ret; 4687 return ret;
4688 }
4222 4689
4223 /* Driver initialization */ 4690 /* Driver initialization */
4224 ibm_thinkpad_ec_found = check_dmi_for_ec(); 4691
4225 IBM_ACPIHANDLE_INIT(ecrd); 4692 IBM_ACPIHANDLE_INIT(ecrd);
4226 IBM_ACPIHANDLE_INIT(ecwr); 4693 IBM_ACPIHANDLE_INIT(ecwr);
4227 4694
@@ -4239,12 +4706,15 @@ static int __init thinkpad_acpi_module_init(void)
4239 thinkpad_acpi_module_exit(); 4706 thinkpad_acpi_module_exit();
4240 return ret; 4707 return ret;
4241 } 4708 }
4709 tp_features.platform_drv_registered = 1;
4710
4242 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver); 4711 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
4243 if (ret) { 4712 if (ret) {
4244 printk(IBM_ERR "unable to create sysfs driver attributes\n"); 4713 printk(IBM_ERR "unable to create sysfs driver attributes\n");
4245 thinkpad_acpi_module_exit(); 4714 thinkpad_acpi_module_exit();
4246 return ret; 4715 return ret;
4247 } 4716 }
4717 tp_features.platform_drv_attrs_registered = 1;
4248 4718
4249 4719
4250 /* Device initialization */ 4720 /* Device initialization */
@@ -4265,6 +4735,22 @@ static int __init thinkpad_acpi_module_init(void)
4265 thinkpad_acpi_module_exit(); 4735 thinkpad_acpi_module_exit();
4266 return ret; 4736 return ret;
4267 } 4737 }
4738 tpacpi_inputdev = input_allocate_device();
4739 if (!tpacpi_inputdev) {
4740 printk(IBM_ERR "unable to allocate input device\n");
4741 thinkpad_acpi_module_exit();
4742 return -ENOMEM;
4743 } else {
4744 /* Prepare input device, but don't register */
4745 tpacpi_inputdev->name = "ThinkPad Extra Buttons";
4746 tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0";
4747 tpacpi_inputdev->id.bustype = BUS_HOST;
4748 tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ?
4749 thinkpad_id.vendor :
4750 PCI_VENDOR_ID_IBM;
4751 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
4752 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
4753 }
4268 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 4754 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
4269 ret = ibm_init(&ibms_init[i]); 4755 ret = ibm_init(&ibms_init[i]);
4270 if (ret >= 0 && *ibms_init[i].param) 4756 if (ret >= 0 && *ibms_init[i].param)
@@ -4274,6 +4760,14 @@ static int __init thinkpad_acpi_module_init(void)
4274 return ret; 4760 return ret;
4275 } 4761 }
4276 } 4762 }
4763 ret = input_register_device(tpacpi_inputdev);
4764 if (ret < 0) {
4765 printk(IBM_ERR "unable to register input device\n");
4766 thinkpad_acpi_module_exit();
4767 return ret;
4768 } else {
4769 tp_features.input_device_registered = 1;
4770 }
4277 4771
4278 return 0; 4772 return 0;
4279} 4773}
@@ -4290,19 +4784,31 @@ static void thinkpad_acpi_module_exit(void)
4290 4784
4291 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); 4785 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
4292 4786
4787 if (tpacpi_inputdev) {
4788 if (tp_features.input_device_registered)
4789 input_unregister_device(tpacpi_inputdev);
4790 else
4791 input_free_device(tpacpi_inputdev);
4792 }
4793
4293 if (tpacpi_hwmon) 4794 if (tpacpi_hwmon)
4294 hwmon_device_unregister(tpacpi_hwmon); 4795 hwmon_device_unregister(tpacpi_hwmon);
4295 4796
4296 if (tpacpi_pdev) 4797 if (tpacpi_pdev)
4297 platform_device_unregister(tpacpi_pdev); 4798 platform_device_unregister(tpacpi_pdev);
4298 4799
4299 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver); 4800 if (tp_features.platform_drv_attrs_registered)
4300 platform_driver_unregister(&tpacpi_pdriver); 4801 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
4802
4803 if (tp_features.platform_drv_registered)
4804 platform_driver_unregister(&tpacpi_pdriver);
4301 4805
4302 if (proc_dir) 4806 if (proc_dir)
4303 remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); 4807 remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
4304 4808
4305 kfree(ibm_thinkpad_ec_found); 4809 kfree(thinkpad_id.bios_version_str);
4810 kfree(thinkpad_id.ec_version_str);
4811 kfree(thinkpad_id.model_str);
4306} 4812}
4307 4813
4308module_init(thinkpad_acpi_module_init); 4814module_init(thinkpad_acpi_module_init);
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index 72d62f2dabb9..082a1cbc16c0 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -32,6 +32,7 @@
32#include <linux/list.h> 32#include <linux/list.h>
33#include <linux/mutex.h> 33#include <linux/mutex.h>
34 34
35#include <linux/nvram.h>
35#include <linux/proc_fs.h> 36#include <linux/proc_fs.h>
36#include <linux/sysfs.h> 37#include <linux/sysfs.h>
37#include <linux/backlight.h> 38#include <linux/backlight.h>
@@ -39,6 +40,7 @@
39#include <linux/platform_device.h> 40#include <linux/platform_device.h>
40#include <linux/hwmon.h> 41#include <linux/hwmon.h>
41#include <linux/hwmon-sysfs.h> 42#include <linux/hwmon-sysfs.h>
43#include <linux/input.h>
42#include <asm/uaccess.h> 44#include <asm/uaccess.h>
43 45
44#include <linux/dmi.h> 46#include <linux/dmi.h>
@@ -48,6 +50,7 @@
48#include <acpi/acpi_drivers.h> 50#include <acpi/acpi_drivers.h>
49#include <acpi/acnamesp.h> 51#include <acpi/acnamesp.h>
50 52
53#include <linux/pci_ids.h>
51 54
52/**************************************************************************** 55/****************************************************************************
53 * Main driver 56 * Main driver
@@ -78,6 +81,11 @@
78#define TP_CMOS_BRIGHTNESS_UP 4 81#define TP_CMOS_BRIGHTNESS_UP 4
79#define TP_CMOS_BRIGHTNESS_DOWN 5 82#define TP_CMOS_BRIGHTNESS_DOWN 5
80 83
84/* ThinkPad CMOS NVRAM constants */
85#define TP_NVRAM_ADDR_BRIGHTNESS 0x5e
86#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07
87#define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0
88
81#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") 89#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
82#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") 90#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
83#define strlencmp(a,b) (strncmp((a), (b), strlen(b))) 91#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
@@ -98,9 +106,13 @@ static const char *str_supported(int is_supported);
98#define vdbg_printk(a_dbg_level, format, arg...) 106#define vdbg_printk(a_dbg_level, format, arg...)
99#endif 107#endif
100 108
109/* Input IDs */
110#define TPACPI_HKEY_INPUT_VENDOR PCI_VENDOR_ID_IBM
111#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */
112#define TPACPI_HKEY_INPUT_VERSION 0x4101
113
101/* ACPI HIDs */ 114/* ACPI HIDs */
102#define IBM_HKEY_HID "IBM0068" 115#define IBM_HKEY_HID "IBM0068"
103#define IBM_PCI_HID "PNP0A03"
104 116
105/* ACPI helpers */ 117/* ACPI helpers */
106static int __must_check acpi_evalf(acpi_handle handle, 118static int __must_check acpi_evalf(acpi_handle handle,
@@ -161,6 +173,7 @@ static int parse_strtoul(const char *buf, unsigned long max,
161static struct platform_device *tpacpi_pdev; 173static struct platform_device *tpacpi_pdev;
162static struct class_device *tpacpi_hwmon; 174static struct class_device *tpacpi_hwmon;
163static struct platform_driver tpacpi_pdriver; 175static struct platform_driver tpacpi_pdriver;
176static struct input_dev *tpacpi_inputdev;
164static int tpacpi_create_driver_attributes(struct device_driver *drv); 177static int tpacpi_create_driver_attributes(struct device_driver *drv);
165static void tpacpi_remove_driver_attributes(struct device_driver *drv); 178static void tpacpi_remove_driver_attributes(struct device_driver *drv);
166 179
@@ -168,9 +181,8 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv);
168static int experimental; 181static int experimental;
169static u32 dbg_level; 182static u32 dbg_level;
170static int force_load; 183static int force_load;
171static char *ibm_thinkpad_ec_found; 184static unsigned int hotkey_report_mode;
172 185
173static char* check_dmi_for_ec(void);
174static int thinkpad_acpi_module_init(void); 186static int thinkpad_acpi_module_init(void);
175static void thinkpad_acpi_module_exit(void); 187static void thinkpad_acpi_module_exit(void);
176 188
@@ -182,7 +194,7 @@ static void thinkpad_acpi_module_exit(void);
182struct ibm_struct; 194struct ibm_struct;
183 195
184struct tp_acpi_drv_struct { 196struct tp_acpi_drv_struct {
185 char *hid; 197 const struct acpi_device_id *hid;
186 struct acpi_driver *driver; 198 struct acpi_driver *driver;
187 199
188 void (*notify) (struct ibm_struct *, u32); 200 void (*notify) (struct ibm_struct *, u32);
@@ -197,6 +209,7 @@ struct ibm_struct {
197 int (*read) (char *); 209 int (*read) (char *);
198 int (*write) (char *); 210 int (*write) (char *);
199 void (*exit) (void); 211 void (*exit) (void);
212 void (*resume) (void);
200 213
201 struct list_head all_drivers; 214 struct list_head all_drivers;
202 215
@@ -228,12 +241,31 @@ static struct {
228 u16 bluetooth:1; 241 u16 bluetooth:1;
229 u16 hotkey:1; 242 u16 hotkey:1;
230 u16 hotkey_mask:1; 243 u16 hotkey_mask:1;
244 u16 hotkey_wlsw:1;
231 u16 light:1; 245 u16 light:1;
232 u16 light_status:1; 246 u16 light_status:1;
233 u16 wan:1; 247 u16 wan:1;
234 u16 fan_ctrl_status_undef:1; 248 u16 fan_ctrl_status_undef:1;
249 u16 input_device_registered:1;
250 u16 platform_drv_registered:1;
251 u16 platform_drv_attrs_registered:1;
235} tp_features; 252} tp_features;
236 253
254struct thinkpad_id_data {
255 unsigned int vendor; /* ThinkPad vendor:
256 * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */
257
258 char *bios_version_str; /* Something like 1ZET51WW (1.03z) */
259 char *ec_version_str; /* Something like 1ZHT51WW-1.04a */
260
261 u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */
262 u16 ec_model;
263
264 char *model_str;
265};
266
267static struct thinkpad_id_data thinkpad_id;
268
237static struct list_head tpacpi_all_drivers; 269static struct list_head tpacpi_all_drivers;
238 270
239static struct ibm_init_struct ibms_init[]; 271static struct ibm_init_struct ibms_init[];
@@ -300,6 +332,7 @@ static int bluetooth_write(char *buf);
300 332
301static struct backlight_device *ibm_backlight_device; 333static struct backlight_device *ibm_backlight_device;
302static int brightness_offset = 0x31; 334static int brightness_offset = 0x31;
335static int brightness_mode;
303 336
304static int brightness_init(struct ibm_init_struct *iibm); 337static int brightness_init(struct ibm_init_struct *iibm);
305static void brightness_exit(void); 338static void brightness_exit(void);
@@ -415,14 +448,14 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc);
415 */ 448 */
416 449
417static int hotkey_orig_status; 450static int hotkey_orig_status;
418static int hotkey_orig_mask; 451static u32 hotkey_orig_mask;
419 452
420static struct mutex hotkey_mutex; 453static struct mutex hotkey_mutex;
421 454
422static int hotkey_init(struct ibm_init_struct *iibm); 455static int hotkey_init(struct ibm_init_struct *iibm);
423static void hotkey_exit(void); 456static void hotkey_exit(void);
424static int hotkey_get(int *status, int *mask); 457static int hotkey_get(int *status, u32 *mask);
425static int hotkey_set(int status, int mask); 458static int hotkey_set(int status, u32 mask);
426static void hotkey_notify(struct ibm_struct *ibm, u32 event); 459static void hotkey_notify(struct ibm_struct *ibm, u32 event);
427static int hotkey_read(char *p); 460static int hotkey_read(char *p);
428static int hotkey_write(char *buf); 461static int hotkey_write(char *buf);
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index d195fb088f4a..8f77949f93dd 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -57,16 +57,11 @@ static int tifm_bus_match(struct device *dev, struct device_driver *drv)
57 return 0; 57 return 0;
58} 58}
59 59
60static int tifm_uevent(struct device *dev, char **envp, int num_envp, 60static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env)
61 char *buffer, int buffer_size)
62{ 61{
63 struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); 62 struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
64 int i = 0;
65 int length = 0;
66 63
67 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 64 if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1)))
68 "TIFM_CARD_TYPE=%s",
69 tifm_media_type_name(sock->type, 1)))
70 return -ENOMEM; 65 return -ENOMEM;
71 66
72 return 0; 67 return 0;