aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/Kconfig2
-rw-r--r--drivers/platform/x86/Kconfig2
-rw-r--r--drivers/platform/x86/acerhdf.c14
-rw-r--r--drivers/platform/x86/asus-laptop.c25
-rw-r--r--drivers/platform/x86/asus_acpi.c19
-rw-r--r--drivers/platform/x86/dell-laptop.c86
-rw-r--r--drivers/platform/x86/dell-wmi.c129
-rw-r--r--drivers/platform/x86/eeepc-laptop.c1423
-rw-r--r--drivers/platform/x86/hp-wmi.c141
-rw-r--r--drivers/platform/x86/intel_menlow.c2
-rw-r--r--drivers/platform/x86/sony-laptop.c2
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c1215
12 files changed, 1999 insertions, 1061 deletions
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 9652c3fe7f5e..8390dca2b4e1 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -1,5 +1,3 @@
1# drivers/platform/Kconfig
2
3if X86 1if X86
4source "drivers/platform/x86/Kconfig" 2source "drivers/platform/x86/Kconfig"
5endif 3endif
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 55ca39dea42e..e5e43121995d 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -334,6 +334,8 @@ config EEEPC_LAPTOP
334 depends on HOTPLUG_PCI 334 depends on HOTPLUG_PCI
335 select BACKLIGHT_CLASS_DEVICE 335 select BACKLIGHT_CLASS_DEVICE
336 select HWMON 336 select HWMON
337 select LEDS_CLASS
338 select NEW_LEDS
337 ---help--- 339 ---help---
338 This driver supports the Fn-Fx keys on Eee PC laptops. 340 This driver supports the Fn-Fx keys on Eee PC laptops.
339 341
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 0a8f735f6c4a..be27aa47e810 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -52,7 +52,7 @@
52 */ 52 */
53#undef START_IN_KERNEL_MODE 53#undef START_IN_KERNEL_MODE
54 54
55#define DRV_VER "0.5.17" 55#define DRV_VER "0.5.18"
56 56
57/* 57/*
58 * According to the Atom N270 datasheet, 58 * According to the Atom N270 datasheet,
@@ -61,7 +61,7 @@
61 * measured by the on-die thermal monitor are within 0 <= Tj <= 90. So, 61 * measured by the on-die thermal monitor are within 0 <= Tj <= 90. So,
62 * assume 89°C is critical temperature. 62 * assume 89°C is critical temperature.
63 */ 63 */
64#define ACERHDF_TEMP_CRIT 89 64#define ACERHDF_TEMP_CRIT 89000
65#define ACERHDF_FAN_OFF 0 65#define ACERHDF_FAN_OFF 0
66#define ACERHDF_FAN_AUTO 1 66#define ACERHDF_FAN_AUTO 1
67 67
@@ -69,7 +69,7 @@
69 * No matter what value the user puts into the fanon variable, turn on the fan 69 * No matter what value the user puts into the fanon variable, turn on the fan
70 * at 80 degree Celsius to prevent hardware damage 70 * at 80 degree Celsius to prevent hardware damage
71 */ 71 */
72#define ACERHDF_MAX_FANON 80 72#define ACERHDF_MAX_FANON 80000
73 73
74/* 74/*
75 * Maximum interval between two temperature checks is 15 seconds, as the die 75 * Maximum interval between two temperature checks is 15 seconds, as the die
@@ -85,8 +85,8 @@ static int kernelmode;
85#endif 85#endif
86 86
87static unsigned int interval = 10; 87static unsigned int interval = 10;
88static unsigned int fanon = 63; 88static unsigned int fanon = 63000;
89static unsigned int fanoff = 58; 89static unsigned int fanoff = 58000;
90static unsigned int verbose; 90static unsigned int verbose;
91static unsigned int fanstate = ACERHDF_FAN_AUTO; 91static unsigned int fanstate = ACERHDF_FAN_AUTO;
92static char force_bios[16]; 92static char force_bios[16];
@@ -171,7 +171,7 @@ static int acerhdf_get_temp(int *temp)
171 if (ec_read(bios_cfg->tempreg, &read_temp)) 171 if (ec_read(bios_cfg->tempreg, &read_temp))
172 return -EINVAL; 172 return -EINVAL;
173 173
174 *temp = read_temp; 174 *temp = read_temp * 1000;
175 175
176 return 0; 176 return 0;
177} 177}
@@ -460,7 +460,7 @@ static int acerhdf_remove(struct platform_device *device)
460 return 0; 460 return 0;
461} 461}
462 462
463static struct dev_pm_ops acerhdf_pm_ops = { 463static const struct dev_pm_ops acerhdf_pm_ops = {
464 .suspend = acerhdf_suspend, 464 .suspend = acerhdf_suspend,
465 .freeze = acerhdf_suspend, 465 .freeze = acerhdf_suspend,
466}; 466};
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index b39d2bb3e75b..61a1c7503658 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -221,6 +221,7 @@ static struct asus_hotk *hotk;
221 */ 221 */
222static const struct acpi_device_id asus_device_ids[] = { 222static const struct acpi_device_id asus_device_ids[] = {
223 {"ATK0100", 0}, 223 {"ATK0100", 0},
224 {"ATK0101", 0},
224 {"", 0}, 225 {"", 0},
225}; 226};
226MODULE_DEVICE_TABLE(acpi, asus_device_ids); 227MODULE_DEVICE_TABLE(acpi, asus_device_ids);
@@ -232,6 +233,7 @@ static void asus_hotk_notify(struct acpi_device *device, u32 event);
232static struct acpi_driver asus_hotk_driver = { 233static struct acpi_driver asus_hotk_driver = {
233 .name = ASUS_HOTK_NAME, 234 .name = ASUS_HOTK_NAME,
234 .class = ASUS_HOTK_CLASS, 235 .class = ASUS_HOTK_CLASS,
236 .owner = THIS_MODULE,
235 .ids = asus_device_ids, 237 .ids = asus_device_ids,
236 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 238 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
237 .ops = { 239 .ops = {
@@ -293,6 +295,11 @@ struct key_entry {
293enum { KE_KEY, KE_END }; 295enum { KE_KEY, KE_END };
294 296
295static struct key_entry asus_keymap[] = { 297static struct key_entry asus_keymap[] = {
298 {KE_KEY, 0x02, KEY_SCREENLOCK},
299 {KE_KEY, 0x05, KEY_WLAN},
300 {KE_KEY, 0x08, KEY_F13},
301 {KE_KEY, 0x17, KEY_ZOOM},
302 {KE_KEY, 0x1f, KEY_BATTERY},
296 {KE_KEY, 0x30, KEY_VOLUMEUP}, 303 {KE_KEY, 0x30, KEY_VOLUMEUP},
297 {KE_KEY, 0x31, KEY_VOLUMEDOWN}, 304 {KE_KEY, 0x31, KEY_VOLUMEDOWN},
298 {KE_KEY, 0x32, KEY_MUTE}, 305 {KE_KEY, 0x32, KEY_MUTE},
@@ -312,8 +319,11 @@ static struct key_entry asus_keymap[] = {
312 {KE_KEY, 0x5F, KEY_WLAN}, 319 {KE_KEY, 0x5F, KEY_WLAN},
313 {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, 320 {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
314 {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, 321 {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
315 {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ 322 {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE},
323 {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE},
324 {KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */
316 {KE_KEY, 0x82, KEY_CAMERA}, 325 {KE_KEY, 0x82, KEY_CAMERA},
326 {KE_KEY, 0x88, KEY_WLAN },
317 {KE_KEY, 0x8A, KEY_PROG1}, 327 {KE_KEY, 0x8A, KEY_PROG1},
318 {KE_KEY, 0x95, KEY_MEDIA}, 328 {KE_KEY, 0x95, KEY_MEDIA},
319 {KE_KEY, 0x99, KEY_PHONE}, 329 {KE_KEY, 0x99, KEY_PHONE},
@@ -1240,9 +1250,6 @@ static int asus_hotk_add(struct acpi_device *device)
1240{ 1250{
1241 int result; 1251 int result;
1242 1252
1243 if (!device)
1244 return -EINVAL;
1245
1246 pr_notice("Asus Laptop Support version %s\n", 1253 pr_notice("Asus Laptop Support version %s\n",
1247 ASUS_LAPTOP_VERSION); 1254 ASUS_LAPTOP_VERSION);
1248 1255
@@ -1283,8 +1290,8 @@ static int asus_hotk_add(struct acpi_device *device)
1283 hotk->ledd_status = 0xFFF; 1290 hotk->ledd_status = 0xFFF;
1284 1291
1285 /* Set initial values of light sensor and level */ 1292 /* Set initial values of light sensor and level */
1286 hotk->light_switch = 1; /* Default to light sensor disabled */ 1293 hotk->light_switch = 0; /* Default to light sensor disabled */
1287 hotk->light_level = 0; /* level 5 for sensor sensitivity */ 1294 hotk->light_level = 5; /* level 5 for sensor sensitivity */
1288 1295
1289 if (ls_switch_handle) 1296 if (ls_switch_handle)
1290 set_light_sens_switch(hotk->light_switch); 1297 set_light_sens_switch(hotk->light_switch);
@@ -1306,9 +1313,6 @@ end:
1306 1313
1307static int asus_hotk_remove(struct acpi_device *device, int type) 1314static int asus_hotk_remove(struct acpi_device *device, int type)
1308{ 1315{
1309 if (!device || !acpi_driver_data(device))
1310 return -EINVAL;
1311
1312 kfree(hotk->name); 1316 kfree(hotk->name);
1313 kfree(hotk); 1317 kfree(hotk);
1314 1318
@@ -1444,9 +1448,6 @@ static int __init asus_laptop_init(void)
1444{ 1448{
1445 int result; 1449 int result;
1446 1450
1447 if (acpi_disabled)
1448 return -ENODEV;
1449
1450 result = acpi_bus_register_driver(&asus_hotk_driver); 1451 result = acpi_bus_register_driver(&asus_hotk_driver);
1451 if (result < 0) 1452 if (result < 0)
1452 return result; 1453 return result;
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index ddf5240ade8c..0c9c53111a22 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -466,6 +466,7 @@ MODULE_DEVICE_TABLE(acpi, asus_device_ids);
466static struct acpi_driver asus_hotk_driver = { 466static struct acpi_driver asus_hotk_driver = {
467 .name = "asus_acpi", 467 .name = "asus_acpi",
468 .class = ACPI_HOTK_CLASS, 468 .class = ACPI_HOTK_CLASS,
469 .owner = THIS_MODULE,
469 .ids = asus_device_ids, 470 .ids = asus_device_ids,
470 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 471 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
471 .ops = { 472 .ops = {
@@ -1334,9 +1335,6 @@ static int asus_hotk_add(struct acpi_device *device)
1334 acpi_status status = AE_OK; 1335 acpi_status status = AE_OK;
1335 int result; 1336 int result;
1336 1337
1337 if (!device)
1338 return -EINVAL;
1339
1340 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n", 1338 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
1341 ASUS_ACPI_VERSION); 1339 ASUS_ACPI_VERSION);
1342 1340
@@ -1392,9 +1390,6 @@ end:
1392 1390
1393static int asus_hotk_remove(struct acpi_device *device, int type) 1391static int asus_hotk_remove(struct acpi_device *device, int type)
1394{ 1392{
1395 if (!device || !acpi_driver_data(device))
1396 return -EINVAL;
1397
1398 asus_hotk_remove_fs(device); 1393 asus_hotk_remove_fs(device);
1399 1394
1400 kfree(hotk); 1395 kfree(hotk);
@@ -1422,21 +1417,17 @@ static int __init asus_acpi_init(void)
1422{ 1417{
1423 int result; 1418 int result;
1424 1419
1425 if (acpi_disabled) 1420 result = acpi_bus_register_driver(&asus_hotk_driver);
1426 return -ENODEV; 1421 if (result < 0)
1422 return result;
1427 1423
1428 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); 1424 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
1429 if (!asus_proc_dir) { 1425 if (!asus_proc_dir) {
1430 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); 1426 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
1427 acpi_bus_unregister_driver(&asus_hotk_driver);
1431 return -ENODEV; 1428 return -ENODEV;
1432 } 1429 }
1433 1430
1434 result = acpi_bus_register_driver(&asus_hotk_driver);
1435 if (result < 0) {
1436 remove_proc_entry(PROC_ASUS, acpi_root_dir);
1437 return result;
1438 }
1439
1440 /* 1431 /*
1441 * This is a bit of a kludge. We only want this module loaded 1432 * This is a bit of a kludge. We only want this module loaded
1442 * for ASUS systems, but there's currently no way to probe the 1433 * for ASUS systems, but there's currently no way to probe the
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 74909c4aaeea..3780994dc8f2 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -58,6 +58,14 @@ static int da_command_code;
58static int da_num_tokens; 58static int da_num_tokens;
59static struct calling_interface_token *da_tokens; 59static struct calling_interface_token *da_tokens;
60 60
61static struct platform_driver platform_driver = {
62 .driver = {
63 .name = "dell-laptop",
64 .owner = THIS_MODULE,
65 }
66};
67
68static struct platform_device *platform_device;
61static struct backlight_device *dell_backlight_device; 69static struct backlight_device *dell_backlight_device;
62static struct rfkill *wifi_rfkill; 70static struct rfkill *wifi_rfkill;
63static struct rfkill *bluetooth_rfkill; 71static struct rfkill *bluetooth_rfkill;
@@ -74,7 +82,7 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
74 { } 82 { }
75}; 83};
76 84
77static void parse_da_table(const struct dmi_header *dm) 85static void __init parse_da_table(const struct dmi_header *dm)
78{ 86{
79 /* Final token is a terminator, so we don't want to copy it */ 87 /* Final token is a terminator, so we don't want to copy it */
80 int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1; 88 int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
@@ -103,7 +111,7 @@ static void parse_da_table(const struct dmi_header *dm)
103 da_num_tokens += tokens; 111 da_num_tokens += tokens;
104} 112}
105 113
106static void find_tokens(const struct dmi_header *dm, void *dummy) 114static void __init find_tokens(const struct dmi_header *dm, void *dummy)
107{ 115{
108 switch (dm->type) { 116 switch (dm->type) {
109 case 0xd4: /* Indexed IO */ 117 case 0xd4: /* Indexed IO */
@@ -197,8 +205,8 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data)
197 dell_send_request(&buffer, 17, 11); 205 dell_send_request(&buffer, 17, 11);
198 status = buffer.output[1]; 206 status = buffer.output[1];
199 207
200 if (status & BIT(bit)) 208 rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));
201 rfkill_set_hw_state(rfkill, !!(status & BIT(16))); 209 rfkill_set_hw_state(rfkill, !(status & BIT(16)));
202} 210}
203 211
204static const struct rfkill_ops dell_rfkill_ops = { 212static const struct rfkill_ops dell_rfkill_ops = {
@@ -206,7 +214,7 @@ static const struct rfkill_ops dell_rfkill_ops = {
206 .query = dell_rfkill_query, 214 .query = dell_rfkill_query,
207}; 215};
208 216
209static int dell_setup_rfkill(void) 217static int __init dell_setup_rfkill(void)
210{ 218{
211 struct calling_interface_buffer buffer; 219 struct calling_interface_buffer buffer;
212 int status; 220 int status;
@@ -217,7 +225,8 @@ static int dell_setup_rfkill(void)
217 status = buffer.output[1]; 225 status = buffer.output[1];
218 226
219 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { 227 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
220 wifi_rfkill = rfkill_alloc("dell-wifi", NULL, RFKILL_TYPE_WLAN, 228 wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
229 RFKILL_TYPE_WLAN,
221 &dell_rfkill_ops, (void *) 1); 230 &dell_rfkill_ops, (void *) 1);
222 if (!wifi_rfkill) { 231 if (!wifi_rfkill) {
223 ret = -ENOMEM; 232 ret = -ENOMEM;
@@ -229,7 +238,8 @@ static int dell_setup_rfkill(void)
229 } 238 }
230 239
231 if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { 240 if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
232 bluetooth_rfkill = rfkill_alloc("dell-bluetooth", NULL, 241 bluetooth_rfkill = rfkill_alloc("dell-bluetooth",
242 &platform_device->dev,
233 RFKILL_TYPE_BLUETOOTH, 243 RFKILL_TYPE_BLUETOOTH,
234 &dell_rfkill_ops, (void *) 2); 244 &dell_rfkill_ops, (void *) 2);
235 if (!bluetooth_rfkill) { 245 if (!bluetooth_rfkill) {
@@ -242,7 +252,9 @@ static int dell_setup_rfkill(void)
242 } 252 }
243 253
244 if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { 254 if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
245 wwan_rfkill = rfkill_alloc("dell-wwan", NULL, RFKILL_TYPE_WWAN, 255 wwan_rfkill = rfkill_alloc("dell-wwan",
256 &platform_device->dev,
257 RFKILL_TYPE_WWAN,
246 &dell_rfkill_ops, (void *) 3); 258 &dell_rfkill_ops, (void *) 3);
247 if (!wwan_rfkill) { 259 if (!wwan_rfkill) {
248 ret = -ENOMEM; 260 ret = -ENOMEM;
@@ -268,6 +280,22 @@ err_wifi:
268 return ret; 280 return ret;
269} 281}
270 282
283static void dell_cleanup_rfkill(void)
284{
285 if (wifi_rfkill) {
286 rfkill_unregister(wifi_rfkill);
287 rfkill_destroy(wifi_rfkill);
288 }
289 if (bluetooth_rfkill) {
290 rfkill_unregister(bluetooth_rfkill);
291 rfkill_destroy(bluetooth_rfkill);
292 }
293 if (wwan_rfkill) {
294 rfkill_unregister(wwan_rfkill);
295 rfkill_destroy(wwan_rfkill);
296 }
297}
298
271static int dell_send_intensity(struct backlight_device *bd) 299static int dell_send_intensity(struct backlight_device *bd)
272{ 300{
273 struct calling_interface_buffer buffer; 301 struct calling_interface_buffer buffer;
@@ -326,11 +354,23 @@ static int __init dell_init(void)
326 return -ENODEV; 354 return -ENODEV;
327 } 355 }
328 356
357 ret = platform_driver_register(&platform_driver);
358 if (ret)
359 goto fail_platform_driver;
360 platform_device = platform_device_alloc("dell-laptop", -1);
361 if (!platform_device) {
362 ret = -ENOMEM;
363 goto fail_platform_device1;
364 }
365 ret = platform_device_add(platform_device);
366 if (ret)
367 goto fail_platform_device2;
368
329 ret = dell_setup_rfkill(); 369 ret = dell_setup_rfkill();
330 370
331 if (ret) { 371 if (ret) {
332 printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n"); 372 printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n");
333 goto out; 373 goto fail_rfkill;
334 } 374 }
335 375
336#ifdef CONFIG_ACPI 376#ifdef CONFIG_ACPI
@@ -352,13 +392,13 @@ static int __init dell_init(void)
352 if (max_intensity) { 392 if (max_intensity) {
353 dell_backlight_device = backlight_device_register( 393 dell_backlight_device = backlight_device_register(
354 "dell_backlight", 394 "dell_backlight",
355 NULL, NULL, 395 &platform_device->dev, NULL,
356 &dell_ops); 396 &dell_ops);
357 397
358 if (IS_ERR(dell_backlight_device)) { 398 if (IS_ERR(dell_backlight_device)) {
359 ret = PTR_ERR(dell_backlight_device); 399 ret = PTR_ERR(dell_backlight_device);
360 dell_backlight_device = NULL; 400 dell_backlight_device = NULL;
361 goto out; 401 goto fail_backlight;
362 } 402 }
363 403
364 dell_backlight_device->props.max_brightness = max_intensity; 404 dell_backlight_device->props.max_brightness = max_intensity;
@@ -368,13 +408,16 @@ static int __init dell_init(void)
368 } 408 }
369 409
370 return 0; 410 return 0;
371out: 411
372 if (wifi_rfkill) 412fail_backlight:
373 rfkill_unregister(wifi_rfkill); 413 dell_cleanup_rfkill();
374 if (bluetooth_rfkill) 414fail_rfkill:
375 rfkill_unregister(bluetooth_rfkill); 415 platform_device_del(platform_device);
376 if (wwan_rfkill) 416fail_platform_device2:
377 rfkill_unregister(wwan_rfkill); 417 platform_device_put(platform_device);
418fail_platform_device1:
419 platform_driver_unregister(&platform_driver);
420fail_platform_driver:
378 kfree(da_tokens); 421 kfree(da_tokens);
379 return ret; 422 return ret;
380} 423}
@@ -382,12 +425,7 @@ out:
382static void __exit dell_exit(void) 425static void __exit dell_exit(void)
383{ 426{
384 backlight_device_unregister(dell_backlight_device); 427 backlight_device_unregister(dell_backlight_device);
385 if (wifi_rfkill) 428 dell_cleanup_rfkill();
386 rfkill_unregister(wifi_rfkill);
387 if (bluetooth_rfkill)
388 rfkill_unregister(bluetooth_rfkill);
389 if (wwan_rfkill)
390 rfkill_unregister(wwan_rfkill);
391} 429}
392 430
393module_init(dell_init); 431module_init(dell_init);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 0f900cc9fa7a..67f3fe71c509 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -31,6 +31,7 @@
31#include <acpi/acpi_drivers.h> 31#include <acpi/acpi_drivers.h>
32#include <linux/acpi.h> 32#include <linux/acpi.h>
33#include <linux/string.h> 33#include <linux/string.h>
34#include <linux/dmi.h>
34 35
35MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); 36MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
36MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver"); 37MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
@@ -38,6 +39,8 @@ MODULE_LICENSE("GPL");
38 39
39#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492" 40#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
40 41
42static int acpi_video;
43
41MODULE_ALIAS("wmi:"DELL_EVENT_GUID); 44MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
42 45
43struct key_entry { 46struct key_entry {
@@ -54,7 +57,7 @@ enum { KE_KEY, KE_SW, KE_IGNORE, KE_END };
54 * via the keyboard controller so should not be sent again. 57 * via the keyboard controller so should not be sent again.
55 */ 58 */
56 59
57static struct key_entry dell_wmi_keymap[] = { 60static struct key_entry dell_legacy_wmi_keymap[] = {
58 {KE_KEY, 0xe045, KEY_PROG1}, 61 {KE_KEY, 0xe045, KEY_PROG1},
59 {KE_KEY, 0xe009, KEY_EJECTCD}, 62 {KE_KEY, 0xe009, KEY_EJECTCD},
60 63
@@ -72,7 +75,7 @@ static struct key_entry dell_wmi_keymap[] = {
72 75
73 /* The next device is at offset 6, the active devices are at 76 /* The next device is at offset 6, the active devices are at
74 offset 8 and the attached devices at offset 10 */ 77 offset 8 and the attached devices at offset 10 */
75 {KE_KEY, 0xe00b, KEY_DISPLAYTOGGLE}, 78 {KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE},
76 79
77 {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE}, 80 {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE},
78 81
@@ -96,6 +99,47 @@ static struct key_entry dell_wmi_keymap[] = {
96 {KE_END, 0} 99 {KE_END, 0}
97}; 100};
98 101
102static bool dell_new_hk_type;
103
104struct dell_new_keymap_entry {
105 u16 scancode;
106 u16 keycode;
107};
108
109struct dell_hotkey_table {
110 struct dmi_header header;
111 struct dell_new_keymap_entry keymap[];
112
113};
114
115static struct key_entry *dell_new_wmi_keymap;
116
117static u16 bios_to_linux_keycode[256] = {
118
119 KEY_MEDIA, KEY_NEXTSONG, KEY_PLAYPAUSE, KEY_PREVIOUSSONG,
120 KEY_STOPCD, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
121 KEY_WWW, KEY_UNKNOWN, KEY_VOLUMEDOWN, KEY_MUTE,
122 KEY_VOLUMEUP, KEY_UNKNOWN, KEY_BATTERY, KEY_EJECTCD,
123 KEY_UNKNOWN, KEY_SLEEP, KEY_PROG1, KEY_BRIGHTNESSDOWN,
124 KEY_BRIGHTNESSUP, KEY_UNKNOWN, KEY_KBDILLUMTOGGLE,
125 KEY_UNKNOWN, KEY_SWITCHVIDEOMODE, KEY_UNKNOWN, KEY_UNKNOWN,
126 KEY_SWITCHVIDEOMODE, KEY_UNKNOWN, KEY_UNKNOWN, KEY_PROG2,
127 KEY_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
137 KEY_PROG3
138};
139
140
141static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
142
99static struct input_dev *dell_wmi_input_dev; 143static struct input_dev *dell_wmi_input_dev;
100 144
101static struct key_entry *dell_wmi_get_entry_by_scancode(int code) 145static struct key_entry *dell_wmi_get_entry_by_scancode(int code)
@@ -164,24 +208,78 @@ static void dell_wmi_notify(u32 value, void *context)
164 obj = (union acpi_object *)response.pointer; 208 obj = (union acpi_object *)response.pointer;
165 209
166 if (obj && obj->type == ACPI_TYPE_BUFFER) { 210 if (obj && obj->type == ACPI_TYPE_BUFFER) {
167 int *buffer = (int *)obj->buffer.pointer; 211 int reported_key;
168 /* 212 u16 *buffer_entry = (u16 *)obj->buffer.pointer;
169 * The upper bytes of the event may contain 213 if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
170 * additional information, so mask them off for the 214 printk(KERN_INFO "dell-wmi: Received unknown WMI event"
171 * scancode lookup 215 " (0x%x)\n", buffer_entry[1]);
172 */ 216 return;
173 key = dell_wmi_get_entry_by_scancode(buffer[1] & 0xFFFF); 217 }
174 if (key) { 218
219 if (dell_new_hk_type)
220 reported_key = (int)buffer_entry[2];
221 else
222 reported_key = (int)buffer_entry[1] & 0xffff;
223
224 key = dell_wmi_get_entry_by_scancode(reported_key);
225
226 if (!key) {
227 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
228 reported_key);
229 } else if ((key->keycode == KEY_BRIGHTNESSUP ||
230 key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video) {
231 /* Don't report brightness notifications that will also
232 * come via ACPI */
233 return;
234 } else {
175 input_report_key(dell_wmi_input_dev, key->keycode, 1); 235 input_report_key(dell_wmi_input_dev, key->keycode, 1);
176 input_sync(dell_wmi_input_dev); 236 input_sync(dell_wmi_input_dev);
177 input_report_key(dell_wmi_input_dev, key->keycode, 0); 237 input_report_key(dell_wmi_input_dev, key->keycode, 0);
178 input_sync(dell_wmi_input_dev); 238 input_sync(dell_wmi_input_dev);
179 } else if (buffer[1] & 0xFFFF) 239 }
180 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
181 buffer[1] & 0xFFFF);
182 } 240 }
183} 241}
184 242
243
244static void setup_new_hk_map(const struct dmi_header *dm)
245{
246
247 int i;
248 int hotkey_num = (dm->length-4)/sizeof(struct dell_new_keymap_entry);
249 struct dell_hotkey_table *table =
250 container_of(dm, struct dell_hotkey_table, header);
251
252 dell_new_wmi_keymap = kzalloc((hotkey_num+1) *
253 sizeof(struct key_entry), GFP_KERNEL);
254
255 for (i = 0; i < hotkey_num; i++) {
256 dell_new_wmi_keymap[i].type = KE_KEY;
257 dell_new_wmi_keymap[i].code = table->keymap[i].scancode;
258 dell_new_wmi_keymap[i].keycode =
259 (table->keymap[i].keycode > 255) ? 0 :
260 bios_to_linux_keycode[table->keymap[i].keycode];
261 }
262
263 dell_new_wmi_keymap[i].type = KE_END;
264 dell_new_wmi_keymap[i].code = 0;
265 dell_new_wmi_keymap[i].keycode = 0;
266
267 dell_wmi_keymap = dell_new_wmi_keymap;
268
269}
270
271
272static void find_hk_type(const struct dmi_header *dm, void *dummy)
273{
274
275 if ((dm->type == 0xb2) && (dm->length > 6)) {
276 dell_new_hk_type = true;
277 setup_new_hk_map(dm);
278 }
279
280}
281
282
185static int __init dell_wmi_input_setup(void) 283static int __init dell_wmi_input_setup(void)
186{ 284{
187 struct key_entry *key; 285 struct key_entry *key;
@@ -226,6 +324,9 @@ static int __init dell_wmi_init(void)
226 int err; 324 int err;
227 325
228 if (wmi_has_guid(DELL_EVENT_GUID)) { 326 if (wmi_has_guid(DELL_EVENT_GUID)) {
327
328 dmi_walk(find_hk_type, NULL);
329
229 err = dell_wmi_input_setup(); 330 err = dell_wmi_input_setup();
230 331
231 if (err) 332 if (err)
@@ -240,6 +341,8 @@ static int __init dell_wmi_init(void)
240 return err; 341 return err;
241 } 342 }
242 343
344 acpi_video = acpi_video_backlight_support();
345
243 } else 346 } else
244 printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); 347 printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
245 348
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index d379e74a05d0..5838c69b2fb3 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * eepc-laptop.c - Asus Eee PC extras 2 * eeepc-laptop.c - Asus Eee PC extras
3 * 3 *
4 * Based on asus_acpi.c as patched for the Eee PC by Asus: 4 * Based on asus_acpi.c as patched for the Eee PC by Asus:
5 * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar 5 * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
@@ -34,20 +34,23 @@
34#include <linux/rfkill.h> 34#include <linux/rfkill.h>
35#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/pci_hotplug.h> 36#include <linux/pci_hotplug.h>
37#include <linux/leds.h>
37 38
38#define EEEPC_LAPTOP_VERSION "0.1" 39#define EEEPC_LAPTOP_VERSION "0.1"
40#define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver"
41#define EEEPC_LAPTOP_FILE "eeepc"
39 42
40#define EEEPC_HOTK_NAME "Eee PC Hotkey Driver" 43#define EEEPC_ACPI_CLASS "hotkey"
41#define EEEPC_HOTK_FILE "eeepc" 44#define EEEPC_ACPI_DEVICE_NAME "Hotkey"
42#define EEEPC_HOTK_CLASS "hotkey" 45#define EEEPC_ACPI_HID "ASUS010"
43#define EEEPC_HOTK_DEVICE_NAME "Hotkey"
44#define EEEPC_HOTK_HID "ASUS010"
45 46
47MODULE_AUTHOR("Corentin Chary, Eric Cooper");
48MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);
49MODULE_LICENSE("GPL");
46 50
47/* 51/*
48 * Definitions for Asus EeePC 52 * Definitions for Asus EeePC
49 */ 53 */
50#define NOTIFY_WLAN_ON 0x10
51#define NOTIFY_BRN_MIN 0x20 54#define NOTIFY_BRN_MIN 0x20
52#define NOTIFY_BRN_MAX 0x2f 55#define NOTIFY_BRN_MAX 0x2f
53 56
@@ -117,60 +120,6 @@ static const char *cm_setv[] = {
117 NULL, NULL, "PBPS", "TPDS" 120 NULL, NULL, "PBPS", "TPDS"
118}; 121};
119 122
120#define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
121
122#define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
123#define EEEPC_EC_SC02 0x63
124#define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
125#define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
126#define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */
127#define EEEPC_EC_SFB3 0xD3
128
129/*
130 * This is the main structure, we can use it to store useful information
131 * about the hotk device
132 */
133struct eeepc_hotk {
134 struct acpi_device *device; /* the device we are in */
135 acpi_handle handle; /* the handle of the hotk device */
136 u32 cm_supported; /* the control methods supported
137 by this BIOS */
138 uint init_flag; /* Init flags */
139 u16 event_count[128]; /* count for each event */
140 struct input_dev *inputdev;
141 u16 *keycode_map;
142 struct rfkill *wlan_rfkill;
143 struct rfkill *bluetooth_rfkill;
144 struct rfkill *wwan3g_rfkill;
145 struct rfkill *wimax_rfkill;
146 struct hotplug_slot *hotplug_slot;
147 struct mutex hotplug_lock;
148};
149
150/* The actual device the driver binds to */
151static struct eeepc_hotk *ehotk;
152
153static void eeepc_rfkill_hotplug(bool real);
154
155/* Platform device/driver */
156static int eeepc_hotk_thaw(struct device *device);
157static int eeepc_hotk_restore(struct device *device);
158
159static struct dev_pm_ops eeepc_pm_ops = {
160 .thaw = eeepc_hotk_thaw,
161 .restore = eeepc_hotk_restore,
162};
163
164static struct platform_driver platform_driver = {
165 .driver = {
166 .name = EEEPC_HOTK_FILE,
167 .owner = THIS_MODULE,
168 .pm = &eeepc_pm_ops,
169 }
170};
171
172static struct platform_device *platform_device;
173
174struct key_entry { 123struct key_entry {
175 char type; 124 char type;
176 u8 code; 125 u8 code;
@@ -179,7 +128,7 @@ struct key_entry {
179 128
180enum { KE_KEY, KE_END }; 129enum { KE_KEY, KE_END };
181 130
182static struct key_entry eeepc_keymap[] = { 131static const struct key_entry eeepc_keymap[] = {
183 /* Sleep already handled via generic ACPI code */ 132 /* Sleep already handled via generic ACPI code */
184 {KE_KEY, 0x10, KEY_WLAN }, 133 {KE_KEY, 0x10, KEY_WLAN },
185 {KE_KEY, 0x11, KEY_WLAN }, 134 {KE_KEY, 0x11, KEY_WLAN },
@@ -187,77 +136,56 @@ static struct key_entry eeepc_keymap[] = {
187 {KE_KEY, 0x13, KEY_MUTE }, 136 {KE_KEY, 0x13, KEY_MUTE },
188 {KE_KEY, 0x14, KEY_VOLUMEDOWN }, 137 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
189 {KE_KEY, 0x15, KEY_VOLUMEUP }, 138 {KE_KEY, 0x15, KEY_VOLUMEUP },
139 {KE_KEY, 0x16, KEY_DISPLAY_OFF },
190 {KE_KEY, 0x1a, KEY_COFFEE }, 140 {KE_KEY, 0x1a, KEY_COFFEE },
191 {KE_KEY, 0x1b, KEY_ZOOM }, 141 {KE_KEY, 0x1b, KEY_ZOOM },
192 {KE_KEY, 0x1c, KEY_PROG2 }, 142 {KE_KEY, 0x1c, KEY_PROG2 },
193 {KE_KEY, 0x1d, KEY_PROG3 }, 143 {KE_KEY, 0x1d, KEY_PROG3 },
194 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, 144 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
195 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP }, 145 {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP },
196 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, 146 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
197 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, 147 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
198 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, 148 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
149 {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */
150 {KE_KEY, 0x38, KEY_F14 },
199 {KE_END, 0}, 151 {KE_END, 0},
200}; 152};
201 153
154
202/* 155/*
203 * The hotkey driver declaration 156 * This is the main structure, we can use it to store useful information
204 */ 157 */
205static int eeepc_hotk_add(struct acpi_device *device); 158struct eeepc_laptop {
206static int eeepc_hotk_remove(struct acpi_device *device, int type); 159 acpi_handle handle; /* the handle of the acpi device */
207static void eeepc_hotk_notify(struct acpi_device *device, u32 event); 160 u32 cm_supported; /* the control methods supported
208 161 by this BIOS */
209static const struct acpi_device_id eeepc_device_ids[] = { 162 u16 event_count[128]; /* count for each event */
210 {EEEPC_HOTK_HID, 0},
211 {"", 0},
212};
213MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
214
215static struct acpi_driver eeepc_hotk_driver = {
216 .name = EEEPC_HOTK_NAME,
217 .class = EEEPC_HOTK_CLASS,
218 .ids = eeepc_device_ids,
219 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
220 .ops = {
221 .add = eeepc_hotk_add,
222 .remove = eeepc_hotk_remove,
223 .notify = eeepc_hotk_notify,
224 },
225};
226 163
227/* PCI hotplug ops */ 164 struct platform_device *platform_device;
228static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); 165 struct device *hwmon_device;
166 struct backlight_device *backlight_device;
229 167
230static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { 168 struct input_dev *inputdev;
231 .owner = THIS_MODULE, 169 struct key_entry *keymap;
232 .get_adapter_status = eeepc_get_adapter_status,
233 .get_power_status = eeepc_get_adapter_status,
234};
235 170
236/* The backlight device /sys/class/backlight */ 171 struct rfkill *wlan_rfkill;
237static struct backlight_device *eeepc_backlight_device; 172 struct rfkill *bluetooth_rfkill;
173 struct rfkill *wwan3g_rfkill;
174 struct rfkill *wimax_rfkill;
238 175
239/* The hwmon device */ 176 struct hotplug_slot *hotplug_slot;
240static struct device *eeepc_hwmon_device; 177 struct mutex hotplug_lock;
241 178
242/* 179 struct led_classdev tpd_led;
243 * The backlight class declaration 180 int tpd_led_wk;
244 */ 181 struct workqueue_struct *led_workqueue;
245static int read_brightness(struct backlight_device *bd); 182 struct work_struct tpd_led_work;
246static int update_bl_status(struct backlight_device *bd);
247static struct backlight_ops eeepcbl_ops = {
248 .get_brightness = read_brightness,
249 .update_status = update_bl_status,
250}; 183};
251 184
252MODULE_AUTHOR("Corentin Chary, Eric Cooper");
253MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
254MODULE_LICENSE("GPL");
255
256/* 185/*
257 * ACPI Helpers 186 * ACPI Helpers
258 */ 187 */
259static int write_acpi_int(acpi_handle handle, const char *method, int val, 188static int write_acpi_int(acpi_handle handle, const char *method, int val)
260 struct acpi_buffer *output)
261{ 189{
262 struct acpi_object_list params; 190 struct acpi_object_list params;
263 union acpi_object in_obj; 191 union acpi_object in_obj;
@@ -268,7 +196,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
268 in_obj.type = ACPI_TYPE_INTEGER; 196 in_obj.type = ACPI_TYPE_INTEGER;
269 in_obj.integer.value = val; 197 in_obj.integer.value = val;
270 198
271 status = acpi_evaluate_object(handle, (char *)method, &params, output); 199 status = acpi_evaluate_object(handle, (char *)method, &params, NULL);
272 return (status == AE_OK ? 0 : -1); 200 return (status == AE_OK ? 0 : -1);
273} 201}
274 202
@@ -287,88 +215,55 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
287 } 215 }
288} 216}
289 217
290static int set_acpi(int cm, int value) 218static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)
291{ 219{
292 if (ehotk->cm_supported & (0x1 << cm)) { 220 const char *method = cm_setv[cm];
293 const char *method = cm_setv[cm];
294 if (method == NULL)
295 return -ENODEV;
296 if (write_acpi_int(ehotk->handle, method, value, NULL))
297 pr_warning("Error writing %s\n", method);
298 }
299 return 0;
300}
301 221
302static int get_acpi(int cm) 222 if (method == NULL)
303{ 223 return -ENODEV;
304 int value = -ENODEV; 224 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
305 if ((ehotk->cm_supported & (0x1 << cm))) { 225 return -ENODEV;
306 const char *method = cm_getv[cm];
307 if (method == NULL)
308 return -ENODEV;
309 if (read_acpi_int(ehotk->handle, method, &value))
310 pr_warning("Error reading %s\n", method);
311 }
312 return value;
313}
314
315/*
316 * Backlight
317 */
318static int read_brightness(struct backlight_device *bd)
319{
320 return get_acpi(CM_ASL_PANELBRIGHT);
321}
322 226
323static int set_brightness(struct backlight_device *bd, int value) 227 if (write_acpi_int(eeepc->handle, method, value))
324{ 228 pr_warning("Error writing %s\n", method);
325 value = max(0, min(15, value)); 229 return 0;
326 return set_acpi(CM_ASL_PANELBRIGHT, value);
327} 230}
328 231
329static int update_bl_status(struct backlight_device *bd) 232static int get_acpi(struct eeepc_laptop *eeepc, int cm)
330{ 233{
331 return set_brightness(bd, bd->props.brightness); 234 const char *method = cm_getv[cm];
332} 235 int value;
333 236
334/* 237 if (method == NULL)
335 * Rfkill helpers 238 return -ENODEV;
336 */ 239 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
240 return -ENODEV;
337 241
338static bool eeepc_wlan_rfkill_blocked(void) 242 if (read_acpi_int(eeepc->handle, method, &value))
339{ 243 pr_warning("Error reading %s\n", method);
340 if (get_acpi(CM_ASL_WLAN) == 1) 244 return value;
341 return false;
342 return true;
343} 245}
344 246
345static int eeepc_rfkill_set(void *data, bool blocked) 247static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
248 acpi_handle *handle)
346{ 249{
347 unsigned long asl = (unsigned long)data; 250 const char *method = cm_setv[cm];
348 int ret; 251 acpi_status status;
349 252
350 if (asl != CM_ASL_WLAN) 253 if (method == NULL)
351 return set_acpi(asl, !blocked); 254 return -ENODEV;
255 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
256 return -ENODEV;
352 257
353 /* hack to avoid panic with rt2860sta */ 258 status = acpi_get_handle(eeepc->handle, (char *)method,
354 if (blocked) 259 handle);
355 eeepc_rfkill_hotplug(false); 260 if (status != AE_OK) {
356 ret = set_acpi(asl, !blocked); 261 pr_warning("Error finding %s\n", method);
357 return ret; 262 return -ENODEV;
263 }
264 return 0;
358} 265}
359 266
360static const struct rfkill_ops eeepc_rfkill_ops = {
361 .set_block = eeepc_rfkill_set,
362};
363
364static void __devinit eeepc_enable_camera(void)
365{
366 /*
367 * If the following call to set_acpi() fails, it's because there's no
368 * camera so we can ignore the error.
369 */
370 set_acpi(CM_ASL_CAMERA, 1);
371}
372 267
373/* 268/*
374 * Sys helpers 269 * Sys helpers
@@ -382,60 +277,63 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
382 return count; 277 return count;
383} 278}
384 279
385static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) 280static ssize_t store_sys_acpi(struct device *dev, int cm,
281 const char *buf, size_t count)
386{ 282{
283 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
387 int rv, value; 284 int rv, value;
388 285
389 rv = parse_arg(buf, count, &value); 286 rv = parse_arg(buf, count, &value);
390 if (rv > 0) 287 if (rv > 0)
391 value = set_acpi(cm, value); 288 value = set_acpi(eeepc, cm, value);
392 if (value < 0) 289 if (value < 0)
393 return value; 290 return -EIO;
394 return rv; 291 return rv;
395} 292}
396 293
397static ssize_t show_sys_acpi(int cm, char *buf) 294static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
398{ 295{
399 int value = get_acpi(cm); 296 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
297 int value = get_acpi(eeepc, cm);
400 298
401 if (value < 0) 299 if (value < 0)
402 return value; 300 return -EIO;
403 return sprintf(buf, "%d\n", value); 301 return sprintf(buf, "%d\n", value);
404} 302}
405 303
406#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ 304#define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
407 static ssize_t show_##_name(struct device *dev, \ 305 static ssize_t show_##_name(struct device *dev, \
408 struct device_attribute *attr, \ 306 struct device_attribute *attr, \
409 char *buf) \ 307 char *buf) \
410 { \ 308 { \
411 return show_sys_acpi(_cm, buf); \ 309 return show_sys_acpi(dev, _cm, buf); \
412 } \ 310 } \
413 static ssize_t store_##_name(struct device *dev, \ 311 static ssize_t store_##_name(struct device *dev, \
414 struct device_attribute *attr, \ 312 struct device_attribute *attr, \
415 const char *buf, size_t count) \ 313 const char *buf, size_t count) \
416 { \ 314 { \
417 return store_sys_acpi(_cm, buf, count); \ 315 return store_sys_acpi(dev, _cm, buf, count); \
418 } \ 316 } \
419 static struct device_attribute dev_attr_##_name = { \ 317 static struct device_attribute dev_attr_##_name = { \
420 .attr = { \ 318 .attr = { \
421 .name = __stringify(_name), \ 319 .name = __stringify(_name), \
422 .mode = 0644 }, \ 320 .mode = _mode }, \
423 .show = show_##_name, \ 321 .show = show_##_name, \
424 .store = store_##_name, \ 322 .store = store_##_name, \
425 } 323 }
426 324
427EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); 325EEEPC_CREATE_DEVICE_ATTR(camera, 0644, CM_ASL_CAMERA);
428EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); 326EEEPC_CREATE_DEVICE_ATTR(cardr, 0644, CM_ASL_CARDREADER);
429EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); 327EEEPC_CREATE_DEVICE_ATTR(disp, 0200, CM_ASL_DISPLAYSWITCH);
430 328
431struct eeepc_cpufv { 329struct eeepc_cpufv {
432 int num; 330 int num;
433 int cur; 331 int cur;
434}; 332};
435 333
436static int get_cpufv(struct eeepc_cpufv *c) 334static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c)
437{ 335{
438 c->cur = get_acpi(CM_ASL_CPUFV); 336 c->cur = get_acpi(eeepc, CM_ASL_CPUFV);
439 c->num = (c->cur >> 8) & 0xff; 337 c->num = (c->cur >> 8) & 0xff;
440 c->cur &= 0xff; 338 c->cur &= 0xff;
441 if (c->cur < 0 || c->num <= 0 || c->num > 12) 339 if (c->cur < 0 || c->num <= 0 || c->num > 12)
@@ -447,11 +345,12 @@ static ssize_t show_available_cpufv(struct device *dev,
447 struct device_attribute *attr, 345 struct device_attribute *attr,
448 char *buf) 346 char *buf)
449{ 347{
348 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
450 struct eeepc_cpufv c; 349 struct eeepc_cpufv c;
451 int i; 350 int i;
452 ssize_t len = 0; 351 ssize_t len = 0;
453 352
454 if (get_cpufv(&c)) 353 if (get_cpufv(eeepc, &c))
455 return -ENODEV; 354 return -ENODEV;
456 for (i = 0; i < c.num; i++) 355 for (i = 0; i < c.num; i++)
457 len += sprintf(buf + len, "%d ", i); 356 len += sprintf(buf + len, "%d ", i);
@@ -463,9 +362,10 @@ static ssize_t show_cpufv(struct device *dev,
463 struct device_attribute *attr, 362 struct device_attribute *attr,
464 char *buf) 363 char *buf)
465{ 364{
365 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
466 struct eeepc_cpufv c; 366 struct eeepc_cpufv c;
467 367
468 if (get_cpufv(&c)) 368 if (get_cpufv(eeepc, &c))
469 return -ENODEV; 369 return -ENODEV;
470 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); 370 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
471} 371}
@@ -474,17 +374,18 @@ static ssize_t store_cpufv(struct device *dev,
474 struct device_attribute *attr, 374 struct device_attribute *attr,
475 const char *buf, size_t count) 375 const char *buf, size_t count)
476{ 376{
377 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
477 struct eeepc_cpufv c; 378 struct eeepc_cpufv c;
478 int rv, value; 379 int rv, value;
479 380
480 if (get_cpufv(&c)) 381 if (get_cpufv(eeepc, &c))
481 return -ENODEV; 382 return -ENODEV;
482 rv = parse_arg(buf, count, &value); 383 rv = parse_arg(buf, count, &value);
483 if (rv < 0) 384 if (rv < 0)
484 return rv; 385 return rv;
485 if (!rv || value < 0 || value >= c.num) 386 if (!rv || value < 0 || value >= c.num)
486 return -EINVAL; 387 return -EINVAL;
487 set_acpi(CM_ASL_CPUFV, value); 388 set_acpi(eeepc, CM_ASL_CPUFV, value);
488 return rv; 389 return rv;
489} 390}
490 391
@@ -516,156 +417,125 @@ static struct attribute_group platform_attribute_group = {
516 .attrs = platform_attributes 417 .attrs = platform_attributes
517}; 418};
518 419
519/* 420static int eeepc_platform_init(struct eeepc_laptop *eeepc)
520 * Hotkey functions
521 */
522static struct key_entry *eepc_get_entry_by_scancode(int code)
523{ 421{
524 struct key_entry *key; 422 int result;
525
526 for (key = eeepc_keymap; key->type != KE_END; key++)
527 if (code == key->code)
528 return key;
529 423
530 return NULL; 424 eeepc->platform_device = platform_device_alloc(EEEPC_LAPTOP_FILE, -1);
531} 425 if (!eeepc->platform_device)
426 return -ENOMEM;
427 platform_set_drvdata(eeepc->platform_device, eeepc);
532 428
533static struct key_entry *eepc_get_entry_by_keycode(int code) 429 result = platform_device_add(eeepc->platform_device);
534{ 430 if (result)
535 struct key_entry *key; 431 goto fail_platform_device;
536 432
537 for (key = eeepc_keymap; key->type != KE_END; key++) 433 result = sysfs_create_group(&eeepc->platform_device->dev.kobj,
538 if (code == key->keycode && key->type == KE_KEY) 434 &platform_attribute_group);
539 return key; 435 if (result)
436 goto fail_sysfs;
437 return 0;
540 438
541 return NULL; 439fail_sysfs:
440 platform_device_del(eeepc->platform_device);
441fail_platform_device:
442 platform_device_put(eeepc->platform_device);
443 return result;
542} 444}
543 445
544static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) 446static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
545{ 447{
546 struct key_entry *key = eepc_get_entry_by_scancode(scancode); 448 sysfs_remove_group(&eeepc->platform_device->dev.kobj,
449 &platform_attribute_group);
450 platform_device_unregister(eeepc->platform_device);
451}
547 452
548 if (key && key->type == KE_KEY) { 453/*
549 *keycode = key->keycode; 454 * LEDs
550 return 0; 455 */
551 } 456/*
457 * These functions actually update the LED's, and are called from a
458 * workqueue. By doing this as separate work rather than when the LED
459 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
460 * potentially bad time, such as a timer interrupt.
461 */
462static void tpd_led_update(struct work_struct *work)
463 {
464 struct eeepc_laptop *eeepc;
552 465
553 return -EINVAL; 466 eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
467
468 set_acpi(eeepc, CM_ASL_TPD, eeepc->tpd_led_wk);
554} 469}
555 470
556static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) 471static void tpd_led_set(struct led_classdev *led_cdev,
472 enum led_brightness value)
557{ 473{
558 struct key_entry *key; 474 struct eeepc_laptop *eeepc;
559 int old_keycode;
560 475
561 if (keycode < 0 || keycode > KEY_MAX) 476 eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
562 return -EINVAL;
563 477
564 key = eepc_get_entry_by_scancode(scancode); 478 eeepc->tpd_led_wk = (value > 0) ? 1 : 0;
565 if (key && key->type == KE_KEY) { 479 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
566 old_keycode = key->keycode;
567 key->keycode = keycode;
568 set_bit(keycode, dev->keybit);
569 if (!eepc_get_entry_by_keycode(old_keycode))
570 clear_bit(old_keycode, dev->keybit);
571 return 0;
572 }
573
574 return -EINVAL;
575} 480}
576 481
577static void cmsg_quirk(int cm, const char *name) 482static int eeepc_led_init(struct eeepc_laptop *eeepc)
578{ 483{
579 int dummy; 484 int rv;
580 485
581 /* Some BIOSes do not report cm although it is avaliable. 486 if (get_acpi(eeepc, CM_ASL_TPD) == -ENODEV)
582 Check if cm_getv[cm] works and, if yes, assume cm should be set. */ 487 return 0;
583 if (!(ehotk->cm_supported & (1 << cm))
584 && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
585 pr_info("%s (%x) not reported by BIOS,"
586 " enabling anyway\n", name, 1 << cm);
587 ehotk->cm_supported |= 1 << cm;
588 }
589}
590 488
591static void cmsg_quirks(void) 489 eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
592{ 490 if (!eeepc->led_workqueue)
593 cmsg_quirk(CM_ASL_LID, "LID"); 491 return -ENOMEM;
594 cmsg_quirk(CM_ASL_TYPE, "TYPE"); 492 INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
595 cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
596 cmsg_quirk(CM_ASL_TPD, "TPD");
597}
598 493
599static int eeepc_hotk_check(void) 494 eeepc->tpd_led.name = "eeepc::touchpad";
600{ 495 eeepc->tpd_led.brightness_set = tpd_led_set;
601 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 496 eeepc->tpd_led.max_brightness = 1;
602 int result;
603 497
604 result = acpi_bus_get_status(ehotk->device); 498 rv = led_classdev_register(&eeepc->platform_device->dev,
605 if (result) 499 &eeepc->tpd_led);
606 return result; 500 if (rv) {
607 if (ehotk->device->status.present) { 501 destroy_workqueue(eeepc->led_workqueue);
608 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, 502 return rv;
609 &buffer)) {
610 pr_err("Hotkey initialization failed\n");
611 return -ENODEV;
612 } else {
613 pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
614 }
615 /* get control methods supported */
616 if (read_acpi_int(ehotk->handle, "CMSG"
617 , &ehotk->cm_supported)) {
618 pr_err("Get control methods supported failed\n");
619 return -ENODEV;
620 } else {
621 cmsg_quirks();
622 pr_info("Get control methods supported: 0x%x\n",
623 ehotk->cm_supported);
624 }
625 } else {
626 pr_err("Hotkey device not present, aborting\n");
627 return -EINVAL;
628 } 503 }
504
629 return 0; 505 return 0;
630} 506}
631 507
632static int notify_brn(void) 508static void eeepc_led_exit(struct eeepc_laptop *eeepc)
633{ 509{
634 /* returns the *previous* brightness, or -1 */ 510 if (eeepc->tpd_led.dev)
635 struct backlight_device *bd = eeepc_backlight_device; 511 led_classdev_unregister(&eeepc->tpd_led);
636 if (bd) { 512 if (eeepc->led_workqueue)
637 int old = bd->props.brightness; 513 destroy_workqueue(eeepc->led_workqueue);
638 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
639 return old;
640 }
641 return -1;
642} 514}
643 515
644static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
645 u8 *value)
646{
647 int val = get_acpi(CM_ASL_WLAN);
648 516
649 if (val == 1 || val == 0) 517/*
650 *value = val; 518 * PCI hotplug (for wlan rfkill)
651 else 519 */
652 return -EINVAL; 520static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
653 521{
654 return 0; 522 if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
523 return false;
524 return true;
655} 525}
656 526
657static void eeepc_rfkill_hotplug(bool real) 527static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
658{ 528{
659 struct pci_dev *dev; 529 struct pci_dev *dev;
660 struct pci_bus *bus; 530 struct pci_bus *bus;
661 bool blocked = real ? eeepc_wlan_rfkill_blocked() : true; 531 bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
662 532
663 if (real && ehotk->wlan_rfkill) 533 if (eeepc->wlan_rfkill)
664 rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); 534 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
665 535
666 mutex_lock(&ehotk->hotplug_lock); 536 mutex_lock(&eeepc->hotplug_lock);
667 537
668 if (ehotk->hotplug_slot) { 538 if (eeepc->hotplug_slot) {
669 bus = pci_find_bus(0, 1); 539 bus = pci_find_bus(0, 1);
670 if (!bus) { 540 if (!bus) {
671 pr_warning("Unable to find PCI bus 1?\n"); 541 pr_warning("Unable to find PCI bus 1?\n");
@@ -695,69 +565,23 @@ static void eeepc_rfkill_hotplug(bool real)
695 } 565 }
696 566
697out_unlock: 567out_unlock:
698 mutex_unlock(&ehotk->hotplug_lock); 568 mutex_unlock(&eeepc->hotplug_lock);
699} 569}
700 570
701static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) 571static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
702{ 572{
573 struct eeepc_laptop *eeepc = data;
574
703 if (event != ACPI_NOTIFY_BUS_CHECK) 575 if (event != ACPI_NOTIFY_BUS_CHECK)
704 return; 576 return;
705 577
706 eeepc_rfkill_hotplug(true); 578 eeepc_rfkill_hotplug(eeepc);
707} 579}
708 580
709static void eeepc_hotk_notify(struct acpi_device *device, u32 event) 581static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
582 char *node)
710{ 583{
711 static struct key_entry *key; 584 acpi_status status;
712 u16 count;
713 int brn = -ENODEV;
714
715 if (!ehotk)
716 return;
717 if (event > ACPI_MAX_SYS_NOTIFY)
718 return;
719 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
720 brn = notify_brn();
721 count = ehotk->event_count[event % 128]++;
722 acpi_bus_generate_proc_event(ehotk->device, event, count);
723 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
724 dev_name(&ehotk->device->dev), event,
725 count);
726 if (ehotk->inputdev) {
727 if (brn != -ENODEV) {
728 /* brightness-change events need special
729 * handling for conversion to key events
730 */
731 if (brn < 0)
732 brn = event;
733 else
734 brn += NOTIFY_BRN_MIN;
735 if (event < brn)
736 event = NOTIFY_BRN_MIN; /* brightness down */
737 else if (event > brn)
738 event = NOTIFY_BRN_MIN + 2; /* ... up */
739 else
740 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
741 }
742 key = eepc_get_entry_by_scancode(event);
743 if (key) {
744 switch (key->type) {
745 case KE_KEY:
746 input_report_key(ehotk->inputdev, key->keycode,
747 1);
748 input_sync(ehotk->inputdev);
749 input_report_key(ehotk->inputdev, key->keycode,
750 0);
751 input_sync(ehotk->inputdev);
752 break;
753 }
754 }
755 }
756}
757
758static int eeepc_register_rfkill_notifier(char *node)
759{
760 acpi_status status = AE_OK;
761 acpi_handle handle; 585 acpi_handle handle;
762 586
763 status = acpi_get_handle(NULL, node, &handle); 587 status = acpi_get_handle(NULL, node, &handle);
@@ -766,7 +590,7 @@ static int eeepc_register_rfkill_notifier(char *node)
766 status = acpi_install_notify_handler(handle, 590 status = acpi_install_notify_handler(handle,
767 ACPI_SYSTEM_NOTIFY, 591 ACPI_SYSTEM_NOTIFY,
768 eeepc_rfkill_notify, 592 eeepc_rfkill_notify,
769 NULL); 593 eeepc);
770 if (ACPI_FAILURE(status)) 594 if (ACPI_FAILURE(status))
771 pr_warning("Failed to register notify on %s\n", node); 595 pr_warning("Failed to register notify on %s\n", node);
772 } else 596 } else
@@ -775,7 +599,8 @@ static int eeepc_register_rfkill_notifier(char *node)
775 return 0; 599 return 0;
776} 600}
777 601
778static void eeepc_unregister_rfkill_notifier(char *node) 602static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
603 char *node)
779{ 604{
780 acpi_status status = AE_OK; 605 acpi_status status = AE_OK;
781 acpi_handle handle; 606 acpi_handle handle;
@@ -792,13 +617,33 @@ static void eeepc_unregister_rfkill_notifier(char *node)
792 } 617 }
793} 618}
794 619
620static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
621 u8 *value)
622{
623 struct eeepc_laptop *eeepc = hotplug_slot->private;
624 int val = get_acpi(eeepc, CM_ASL_WLAN);
625
626 if (val == 1 || val == 0)
627 *value = val;
628 else
629 return -EINVAL;
630
631 return 0;
632}
633
795static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) 634static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
796{ 635{
797 kfree(hotplug_slot->info); 636 kfree(hotplug_slot->info);
798 kfree(hotplug_slot); 637 kfree(hotplug_slot);
799} 638}
800 639
801static int eeepc_setup_pci_hotplug(void) 640static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
641 .owner = THIS_MODULE,
642 .get_adapter_status = eeepc_get_adapter_status,
643 .get_power_status = eeepc_get_adapter_status,
644};
645
646static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
802{ 647{
803 int ret = -ENOMEM; 648 int ret = -ENOMEM;
804 struct pci_bus *bus = pci_find_bus(0, 1); 649 struct pci_bus *bus = pci_find_bus(0, 1);
@@ -808,22 +653,22 @@ static int eeepc_setup_pci_hotplug(void)
808 return -ENODEV; 653 return -ENODEV;
809 } 654 }
810 655
811 ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); 656 eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
812 if (!ehotk->hotplug_slot) 657 if (!eeepc->hotplug_slot)
813 goto error_slot; 658 goto error_slot;
814 659
815 ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), 660 eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
816 GFP_KERNEL); 661 GFP_KERNEL);
817 if (!ehotk->hotplug_slot->info) 662 if (!eeepc->hotplug_slot->info)
818 goto error_info; 663 goto error_info;
819 664
820 ehotk->hotplug_slot->private = ehotk; 665 eeepc->hotplug_slot->private = eeepc;
821 ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; 666 eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
822 ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; 667 eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
823 eeepc_get_adapter_status(ehotk->hotplug_slot, 668 eeepc_get_adapter_status(eeepc->hotplug_slot,
824 &ehotk->hotplug_slot->info->adapter_status); 669 &eeepc->hotplug_slot->info->adapter_status);
825 670
826 ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); 671 ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
827 if (ret) { 672 if (ret) {
828 pr_err("Unable to register hotplug slot - %d\n", ret); 673 pr_err("Unable to register hotplug slot - %d\n", ret);
829 goto error_register; 674 goto error_register;
@@ -832,17 +677,156 @@ static int eeepc_setup_pci_hotplug(void)
832 return 0; 677 return 0;
833 678
834error_register: 679error_register:
835 kfree(ehotk->hotplug_slot->info); 680 kfree(eeepc->hotplug_slot->info);
836error_info: 681error_info:
837 kfree(ehotk->hotplug_slot); 682 kfree(eeepc->hotplug_slot);
838 ehotk->hotplug_slot = NULL; 683 eeepc->hotplug_slot = NULL;
839error_slot: 684error_slot:
840 return ret; 685 return ret;
841} 686}
842 687
688/*
689 * Rfkill devices
690 */
691static int eeepc_rfkill_set(void *data, bool blocked)
692{
693 acpi_handle handle = data;
694
695 return write_acpi_int(handle, NULL, !blocked);
696}
697
698static const struct rfkill_ops eeepc_rfkill_ops = {
699 .set_block = eeepc_rfkill_set,
700};
701
702static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
703 struct rfkill **rfkill,
704 const char *name,
705 enum rfkill_type type, int cm)
706{
707 acpi_handle handle;
708 int result;
709
710 result = acpi_setter_handle(eeepc, cm, &handle);
711 if (result < 0)
712 return result;
713
714 *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
715 &eeepc_rfkill_ops, handle);
716
717 if (!*rfkill)
718 return -EINVAL;
719
720 rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
721 result = rfkill_register(*rfkill);
722 if (result) {
723 rfkill_destroy(*rfkill);
724 *rfkill = NULL;
725 return result;
726 }
727 return 0;
728}
729
730static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
731{
732 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
733 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
734 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
735 if (eeepc->wlan_rfkill) {
736 rfkill_unregister(eeepc->wlan_rfkill);
737 rfkill_destroy(eeepc->wlan_rfkill);
738 eeepc->wlan_rfkill = NULL;
739 }
740 /*
741 * Refresh pci hotplug in case the rfkill state was changed after
742 * eeepc_unregister_rfkill_notifier()
743 */
744 eeepc_rfkill_hotplug(eeepc);
745 if (eeepc->hotplug_slot)
746 pci_hp_deregister(eeepc->hotplug_slot);
747
748 if (eeepc->bluetooth_rfkill) {
749 rfkill_unregister(eeepc->bluetooth_rfkill);
750 rfkill_destroy(eeepc->bluetooth_rfkill);
751 eeepc->bluetooth_rfkill = NULL;
752 }
753 if (eeepc->wwan3g_rfkill) {
754 rfkill_unregister(eeepc->wwan3g_rfkill);
755 rfkill_destroy(eeepc->wwan3g_rfkill);
756 eeepc->wwan3g_rfkill = NULL;
757 }
758 if (eeepc->wimax_rfkill) {
759 rfkill_unregister(eeepc->wimax_rfkill);
760 rfkill_destroy(eeepc->wimax_rfkill);
761 eeepc->wimax_rfkill = NULL;
762 }
763}
764
765static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
766{
767 int result = 0;
768
769 mutex_init(&eeepc->hotplug_lock);
770
771 result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
772 "eeepc-wlan", RFKILL_TYPE_WLAN,
773 CM_ASL_WLAN);
774
775 if (result && result != -ENODEV)
776 goto exit;
777
778 result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
779 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
780 CM_ASL_BLUETOOTH);
781
782 if (result && result != -ENODEV)
783 goto exit;
784
785 result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
786 "eeepc-wwan3g", RFKILL_TYPE_WWAN,
787 CM_ASL_3G);
788
789 if (result && result != -ENODEV)
790 goto exit;
791
792 result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
793 "eeepc-wimax", RFKILL_TYPE_WIMAX,
794 CM_ASL_WIMAX);
795
796 if (result && result != -ENODEV)
797 goto exit;
798
799 result = eeepc_setup_pci_hotplug(eeepc);
800 /*
801 * If we get -EBUSY then something else is handling the PCI hotplug -
802 * don't fail in this case
803 */
804 if (result == -EBUSY)
805 result = 0;
806
807 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
808 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
809 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
810 /*
811 * Refresh pci hotplug in case the rfkill state was changed during
812 * setup.
813 */
814 eeepc_rfkill_hotplug(eeepc);
815
816exit:
817 if (result && result != -ENODEV)
818 eeepc_rfkill_exit(eeepc);
819 return result;
820}
821
822/*
823 * Platform driver - hibernate/resume callbacks
824 */
843static int eeepc_hotk_thaw(struct device *device) 825static int eeepc_hotk_thaw(struct device *device)
844{ 826{
845 if (ehotk->wlan_rfkill) { 827 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
828
829 if (eeepc->wlan_rfkill) {
846 bool wlan; 830 bool wlan;
847 831
848 /* 832 /*
@@ -850,8 +834,8 @@ static int eeepc_hotk_thaw(struct device *device)
850 * during suspend. Normally it restores it on resume, but 834 * during suspend. Normally it restores it on resume, but
851 * we should kick it ourselves in case hibernation is aborted. 835 * we should kick it ourselves in case hibernation is aborted.
852 */ 836 */
853 wlan = get_acpi(CM_ASL_WLAN); 837 wlan = get_acpi(eeepc, CM_ASL_WLAN);
854 set_acpi(CM_ASL_WLAN, wlan); 838 set_acpi(eeepc, CM_ASL_WLAN, wlan);
855 } 839 }
856 840
857 return 0; 841 return 0;
@@ -859,70 +843,96 @@ static int eeepc_hotk_thaw(struct device *device)
859 843
860static int eeepc_hotk_restore(struct device *device) 844static int eeepc_hotk_restore(struct device *device)
861{ 845{
846 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
847
862 /* Refresh both wlan rfkill state and pci hotplug */ 848 /* Refresh both wlan rfkill state and pci hotplug */
863 if (ehotk->wlan_rfkill) 849 if (eeepc->wlan_rfkill)
864 eeepc_rfkill_hotplug(true); 850 eeepc_rfkill_hotplug(eeepc);
865 851
866 if (ehotk->bluetooth_rfkill) 852 if (eeepc->bluetooth_rfkill)
867 rfkill_set_sw_state(ehotk->bluetooth_rfkill, 853 rfkill_set_sw_state(eeepc->bluetooth_rfkill,
868 get_acpi(CM_ASL_BLUETOOTH) != 1); 854 get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
869 if (ehotk->wwan3g_rfkill) 855 if (eeepc->wwan3g_rfkill)
870 rfkill_set_sw_state(ehotk->wwan3g_rfkill, 856 rfkill_set_sw_state(eeepc->wwan3g_rfkill,
871 get_acpi(CM_ASL_3G) != 1); 857 get_acpi(eeepc, CM_ASL_3G) != 1);
872 if (ehotk->wimax_rfkill) 858 if (eeepc->wimax_rfkill)
873 rfkill_set_sw_state(ehotk->wimax_rfkill, 859 rfkill_set_sw_state(eeepc->wimax_rfkill,
874 get_acpi(CM_ASL_WIMAX) != 1); 860 get_acpi(eeepc, CM_ASL_WIMAX) != 1);
875 861
876 return 0; 862 return 0;
877} 863}
878 864
865static const struct dev_pm_ops eeepc_pm_ops = {
866 .thaw = eeepc_hotk_thaw,
867 .restore = eeepc_hotk_restore,
868};
869
870static struct platform_driver platform_driver = {
871 .driver = {
872 .name = EEEPC_LAPTOP_FILE,
873 .owner = THIS_MODULE,
874 .pm = &eeepc_pm_ops,
875 }
876};
877
879/* 878/*
880 * Hwmon 879 * Hwmon device
881 */ 880 */
881
882#define EEEPC_EC_SC00 0x61
883#define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
884#define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
885#define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
886
887#define EEEPC_EC_SFB0 0xD0
888#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
889
882static int eeepc_get_fan_pwm(void) 890static int eeepc_get_fan_pwm(void)
883{ 891{
884 int value = 0; 892 u8 value = 0;
885 893
886 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value); 894 ec_read(EEEPC_EC_FAN_PWM, &value);
887 value = value * 255 / 100; 895 return value * 255 / 100;
888 return (value);
889} 896}
890 897
891static void eeepc_set_fan_pwm(int value) 898static void eeepc_set_fan_pwm(int value)
892{ 899{
893 value = SENSORS_LIMIT(value, 0, 255); 900 value = SENSORS_LIMIT(value, 0, 255);
894 value = value * 100 / 255; 901 value = value * 100 / 255;
895 ec_write(EEEPC_EC_SC02, value); 902 ec_write(EEEPC_EC_FAN_PWM, value);
896} 903}
897 904
898static int eeepc_get_fan_rpm(void) 905static int eeepc_get_fan_rpm(void)
899{ 906{
900 int high = 0; 907 u8 high = 0;
901 int low = 0; 908 u8 low = 0;
902 909
903 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high); 910 ec_read(EEEPC_EC_FAN_HRPM, &high);
904 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low); 911 ec_read(EEEPC_EC_FAN_LRPM, &low);
905 return (high << 8 | low); 912 return high << 8 | low;
906} 913}
907 914
908static int eeepc_get_fan_ctrl(void) 915static int eeepc_get_fan_ctrl(void)
909{ 916{
910 int value = 0; 917 u8 value = 0;
911 918
912 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); 919 ec_read(EEEPC_EC_FAN_CTRL, &value);
913 return ((value & 0x02 ? 1 : 0)); 920 if (value & 0x02)
921 return 1; /* manual */
922 else
923 return 2; /* automatic */
914} 924}
915 925
916static void eeepc_set_fan_ctrl(int manual) 926static void eeepc_set_fan_ctrl(int manual)
917{ 927{
918 int value = 0; 928 u8 value = 0;
919 929
920 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); 930 ec_read(EEEPC_EC_FAN_CTRL, &value);
921 if (manual) 931 if (manual == 1)
922 value |= 0x02; 932 value |= 0x02;
923 else 933 else
924 value &= ~0x02; 934 value &= ~0x02;
925 ec_write(EEEPC_EC_SFB3, value); 935 ec_write(EEEPC_EC_FAN_CTRL, value);
926} 936}
927 937
928static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count) 938static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
@@ -980,348 +990,485 @@ static struct attribute_group hwmon_attribute_group = {
980 .attrs = hwmon_attributes 990 .attrs = hwmon_attributes
981}; 991};
982 992
983/* 993static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc)
984 * exit/init
985 */
986static void eeepc_backlight_exit(void)
987{ 994{
988 if (eeepc_backlight_device) 995 struct device *hwmon;
989 backlight_device_unregister(eeepc_backlight_device); 996
990 eeepc_backlight_device = NULL; 997 hwmon = eeepc->hwmon_device;
998 if (!hwmon)
999 return;
1000 sysfs_remove_group(&hwmon->kobj,
1001 &hwmon_attribute_group);
1002 hwmon_device_unregister(hwmon);
1003 eeepc->hwmon_device = NULL;
991} 1004}
992 1005
993static void eeepc_rfkill_exit(void) 1006static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
994{ 1007{
995 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5"); 1008 struct device *hwmon;
996 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); 1009 int result;
997 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); 1010
998 if (ehotk->wlan_rfkill) { 1011 hwmon = hwmon_device_register(&eeepc->platform_device->dev);
999 rfkill_unregister(ehotk->wlan_rfkill); 1012 if (IS_ERR(hwmon)) {
1000 rfkill_destroy(ehotk->wlan_rfkill); 1013 pr_err("Could not register eeepc hwmon device\n");
1001 ehotk->wlan_rfkill = NULL; 1014 eeepc->hwmon_device = NULL;
1002 } 1015 return PTR_ERR(hwmon);
1003 /*
1004 * Refresh pci hotplug in case the rfkill state was changed after
1005 * eeepc_unregister_rfkill_notifier()
1006 */
1007 eeepc_rfkill_hotplug(true);
1008 if (ehotk->hotplug_slot)
1009 pci_hp_deregister(ehotk->hotplug_slot);
1010
1011 if (ehotk->bluetooth_rfkill) {
1012 rfkill_unregister(ehotk->bluetooth_rfkill);
1013 rfkill_destroy(ehotk->bluetooth_rfkill);
1014 ehotk->bluetooth_rfkill = NULL;
1015 }
1016 if (ehotk->wwan3g_rfkill) {
1017 rfkill_unregister(ehotk->wwan3g_rfkill);
1018 rfkill_destroy(ehotk->wwan3g_rfkill);
1019 ehotk->wwan3g_rfkill = NULL;
1020 }
1021 if (ehotk->wimax_rfkill) {
1022 rfkill_unregister(ehotk->wimax_rfkill);
1023 rfkill_destroy(ehotk->wimax_rfkill);
1024 ehotk->wimax_rfkill = NULL;
1025 } 1016 }
1017 eeepc->hwmon_device = hwmon;
1018 result = sysfs_create_group(&hwmon->kobj,
1019 &hwmon_attribute_group);
1020 if (result)
1021 eeepc_hwmon_exit(eeepc);
1022 return result;
1026} 1023}
1027 1024
1028static void eeepc_input_exit(void) 1025/*
1026 * Backlight device
1027 */
1028static int read_brightness(struct backlight_device *bd)
1029{ 1029{
1030 if (ehotk->inputdev) 1030 struct eeepc_laptop *eeepc = bl_get_data(bd);
1031 input_unregister_device(ehotk->inputdev); 1031
1032 return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
1032} 1033}
1033 1034
1034static void eeepc_hwmon_exit(void) 1035static int set_brightness(struct backlight_device *bd, int value)
1035{ 1036{
1036 struct device *hwmon; 1037 struct eeepc_laptop *eeepc = bl_get_data(bd);
1037 1038
1038 hwmon = eeepc_hwmon_device; 1039 return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
1039 if (!hwmon)
1040 return ;
1041 sysfs_remove_group(&hwmon->kobj,
1042 &hwmon_attribute_group);
1043 hwmon_device_unregister(hwmon);
1044 eeepc_hwmon_device = NULL;
1045} 1040}
1046 1041
1047static int eeepc_new_rfkill(struct rfkill **rfkill, 1042static int update_bl_status(struct backlight_device *bd)
1048 const char *name, struct device *dev,
1049 enum rfkill_type type, int cm)
1050{ 1043{
1051 int result; 1044 return set_brightness(bd, bd->props.brightness);
1045}
1052 1046
1053 result = get_acpi(cm); 1047static struct backlight_ops eeepcbl_ops = {
1054 if (result < 0) 1048 .get_brightness = read_brightness,
1055 return result; 1049 .update_status = update_bl_status,
1050};
1056 1051
1057 *rfkill = rfkill_alloc(name, dev, type, 1052static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1058 &eeepc_rfkill_ops, (void *)(unsigned long)cm); 1053{
1054 struct backlight_device *bd = eeepc->backlight_device;
1055 int old = bd->props.brightness;
1059 1056
1060 if (!*rfkill) 1057 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1061 return -EINVAL;
1062 1058
1063 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); 1059 return old;
1064 result = rfkill_register(*rfkill);
1065 if (result) {
1066 rfkill_destroy(*rfkill);
1067 *rfkill = NULL;
1068 return result;
1069 }
1070 return 0;
1071} 1060}
1072 1061
1073 1062static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1074static int eeepc_rfkill_init(struct device *dev)
1075{ 1063{
1076 int result = 0; 1064 struct backlight_device *bd;
1077
1078 mutex_init(&ehotk->hotplug_lock);
1079 1065
1080 result = eeepc_new_rfkill(&ehotk->wlan_rfkill, 1066 bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1081 "eeepc-wlan", dev, 1067 &eeepc->platform_device->dev,
1082 RFKILL_TYPE_WLAN, CM_ASL_WLAN); 1068 eeepc, &eeepcbl_ops);
1069 if (IS_ERR(bd)) {
1070 pr_err("Could not register eeepc backlight device\n");
1071 eeepc->backlight_device = NULL;
1072 return PTR_ERR(bd);
1073 }
1074 eeepc->backlight_device = bd;
1075 bd->props.max_brightness = 15;
1076 bd->props.brightness = read_brightness(bd);
1077 bd->props.power = FB_BLANK_UNBLANK;
1078 backlight_update_status(bd);
1079 return 0;
1080}
1083 1081
1084 if (result && result != -ENODEV) 1082static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1085 goto exit; 1083{
1084 if (eeepc->backlight_device)
1085 backlight_device_unregister(eeepc->backlight_device);
1086 eeepc->backlight_device = NULL;
1087}
1086 1088
1087 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
1088 "eeepc-bluetooth", dev,
1089 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
1090 1089
1091 if (result && result != -ENODEV) 1090/*
1092 goto exit; 1091 * Input device (i.e. hotkeys)
1092 */
1093static struct key_entry *eeepc_get_entry_by_scancode(
1094 struct eeepc_laptop *eeepc,
1095 int code)
1096{
1097 struct key_entry *key;
1093 1098
1094 result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, 1099 for (key = eeepc->keymap; key->type != KE_END; key++)
1095 "eeepc-wwan3g", dev, 1100 if (code == key->code)
1096 RFKILL_TYPE_WWAN, CM_ASL_3G); 1101 return key;
1097 1102
1098 if (result && result != -ENODEV) 1103 return NULL;
1099 goto exit; 1104}
1100 1105
1101 result = eeepc_new_rfkill(&ehotk->wimax_rfkill, 1106static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1102 "eeepc-wimax", dev, 1107{
1103 RFKILL_TYPE_WIMAX, CM_ASL_WIMAX); 1108 static struct key_entry *key;
1104 1109
1105 if (result && result != -ENODEV) 1110 key = eeepc_get_entry_by_scancode(eeepc, event);
1106 goto exit; 1111 if (key) {
1112 switch (key->type) {
1113 case KE_KEY:
1114 input_report_key(eeepc->inputdev, key->keycode,
1115 1);
1116 input_sync(eeepc->inputdev);
1117 input_report_key(eeepc->inputdev, key->keycode,
1118 0);
1119 input_sync(eeepc->inputdev);
1120 break;
1121 }
1122 }
1123}
1107 1124
1108 result = eeepc_setup_pci_hotplug(); 1125static struct key_entry *eeepc_get_entry_by_keycode(
1109 /* 1126 struct eeepc_laptop *eeepc, int code)
1110 * If we get -EBUSY then something else is handling the PCI hotplug - 1127{
1111 * don't fail in this case 1128 struct key_entry *key;
1112 */
1113 if (result == -EBUSY)
1114 result = 0;
1115 1129
1116 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5"); 1130 for (key = eeepc->keymap; key->type != KE_END; key++)
1117 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); 1131 if (code == key->keycode && key->type == KE_KEY)
1118 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); 1132 return key;
1119 /*
1120 * Refresh pci hotplug in case the rfkill state was changed during
1121 * setup.
1122 */
1123 eeepc_rfkill_hotplug(true);
1124 1133
1125exit: 1134 return NULL;
1126 if (result && result != -ENODEV)
1127 eeepc_rfkill_exit();
1128 return result;
1129} 1135}
1130 1136
1131static int eeepc_backlight_init(struct device *dev) 1137static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
1132{ 1138{
1133 struct backlight_device *bd; 1139 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1140 struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode);
1134 1141
1135 bd = backlight_device_register(EEEPC_HOTK_FILE, dev, 1142 if (key && key->type == KE_KEY) {
1136 NULL, &eeepcbl_ops); 1143 *keycode = key->keycode;
1137 if (IS_ERR(bd)) { 1144 return 0;
1138 pr_err("Could not register eeepc backlight device\n");
1139 eeepc_backlight_device = NULL;
1140 return PTR_ERR(bd);
1141 } 1145 }
1142 eeepc_backlight_device = bd; 1146
1143 bd->props.max_brightness = 15; 1147 return -EINVAL;
1144 bd->props.brightness = read_brightness(NULL);
1145 bd->props.power = FB_BLANK_UNBLANK;
1146 backlight_update_status(bd);
1147 return 0;
1148} 1148}
1149 1149
1150static int eeepc_hwmon_init(struct device *dev) 1150static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
1151{ 1151{
1152 struct device *hwmon; 1152 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1153 int result; 1153 struct key_entry *key;
1154 int old_keycode;
1154 1155
1155 hwmon = hwmon_device_register(dev); 1156 if (keycode < 0 || keycode > KEY_MAX)
1156 if (IS_ERR(hwmon)) { 1157 return -EINVAL;
1157 pr_err("Could not register eeepc hwmon device\n"); 1158
1158 eeepc_hwmon_device = NULL; 1159 key = eeepc_get_entry_by_scancode(eeepc, scancode);
1159 return PTR_ERR(hwmon); 1160 if (key && key->type == KE_KEY) {
1161 old_keycode = key->keycode;
1162 key->keycode = keycode;
1163 set_bit(keycode, dev->keybit);
1164 if (!eeepc_get_entry_by_keycode(eeepc, old_keycode))
1165 clear_bit(old_keycode, dev->keybit);
1166 return 0;
1160 } 1167 }
1161 eeepc_hwmon_device = hwmon; 1168
1162 result = sysfs_create_group(&hwmon->kobj, 1169 return -EINVAL;
1163 &hwmon_attribute_group);
1164 if (result)
1165 eeepc_hwmon_exit();
1166 return result;
1167} 1170}
1168 1171
1169static int eeepc_input_init(struct device *dev) 1172static int eeepc_input_init(struct eeepc_laptop *eeepc)
1170{ 1173{
1171 const struct key_entry *key; 1174 const struct key_entry *key;
1172 int result; 1175 int result;
1173 1176
1174 ehotk->inputdev = input_allocate_device(); 1177 eeepc->inputdev = input_allocate_device();
1175 if (!ehotk->inputdev) { 1178 if (!eeepc->inputdev) {
1176 pr_info("Unable to allocate input device\n"); 1179 pr_info("Unable to allocate input device\n");
1177 return -ENOMEM; 1180 return -ENOMEM;
1178 } 1181 }
1179 ehotk->inputdev->name = "Asus EeePC extra buttons"; 1182 eeepc->inputdev->name = "Asus EeePC extra buttons";
1180 ehotk->inputdev->dev.parent = dev; 1183 eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
1181 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; 1184 eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0";
1182 ehotk->inputdev->id.bustype = BUS_HOST; 1185 eeepc->inputdev->id.bustype = BUS_HOST;
1183 ehotk->inputdev->getkeycode = eeepc_getkeycode; 1186 eeepc->inputdev->getkeycode = eeepc_getkeycode;
1184 ehotk->inputdev->setkeycode = eeepc_setkeycode; 1187 eeepc->inputdev->setkeycode = eeepc_setkeycode;
1185 1188 input_set_drvdata(eeepc->inputdev, eeepc);
1189
1190 eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap),
1191 GFP_KERNEL);
1186 for (key = eeepc_keymap; key->type != KE_END; key++) { 1192 for (key = eeepc_keymap; key->type != KE_END; key++) {
1187 switch (key->type) { 1193 switch (key->type) {
1188 case KE_KEY: 1194 case KE_KEY:
1189 set_bit(EV_KEY, ehotk->inputdev->evbit); 1195 set_bit(EV_KEY, eeepc->inputdev->evbit);
1190 set_bit(key->keycode, ehotk->inputdev->keybit); 1196 set_bit(key->keycode, eeepc->inputdev->keybit);
1191 break; 1197 break;
1192 } 1198 }
1193 } 1199 }
1194 result = input_register_device(ehotk->inputdev); 1200 result = input_register_device(eeepc->inputdev);
1195 if (result) { 1201 if (result) {
1196 pr_info("Unable to register input device\n"); 1202 pr_info("Unable to register input device\n");
1197 input_free_device(ehotk->inputdev); 1203 input_free_device(eeepc->inputdev);
1198 return result; 1204 return result;
1199 } 1205 }
1200 return 0; 1206 return 0;
1201} 1207}
1202 1208
1203static int __devinit eeepc_hotk_add(struct acpi_device *device) 1209static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1204{ 1210{
1205 struct device *dev; 1211 if (eeepc->inputdev) {
1212 input_unregister_device(eeepc->inputdev);
1213 kfree(eeepc->keymap);
1214 }
1215}
1216
1217/*
1218 * ACPI driver
1219 */
1220static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1221{
1222 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1223 u16 count;
1224
1225 if (event > ACPI_MAX_SYS_NOTIFY)
1226 return;
1227 count = eeepc->event_count[event % 128]++;
1228 acpi_bus_generate_proc_event(device, event, count);
1229 acpi_bus_generate_netlink_event(device->pnp.device_class,
1230 dev_name(&device->dev), event,
1231 count);
1232
1233 /* Brightness events are special */
1234 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
1235
1236 /* Ignore them completely if the acpi video driver is used */
1237 if (eeepc->backlight_device != NULL) {
1238 int old_brightness, new_brightness;
1239
1240 /* Update the backlight device. */
1241 old_brightness = eeepc_backlight_notify(eeepc);
1242
1243 /* Convert event to keypress (obsolescent hack) */
1244 new_brightness = event - NOTIFY_BRN_MIN;
1245
1246 if (new_brightness < old_brightness) {
1247 event = NOTIFY_BRN_MIN; /* brightness down */
1248 } else if (new_brightness > old_brightness) {
1249 event = NOTIFY_BRN_MAX; /* brightness up */
1250 } else {
1251 /*
1252 * no change in brightness - already at min/max,
1253 * event will be desired value (or else ignored)
1254 */
1255 }
1256 eeepc_input_notify(eeepc, event);
1257 }
1258 } else {
1259 /* Everything else is a bona-fide keypress event */
1260 eeepc_input_notify(eeepc, event);
1261 }
1262}
1263
1264static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1265{
1266 int dummy;
1267
1268 /* Some BIOSes do not report cm although it is avaliable.
1269 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1270 if (!(eeepc->cm_supported & (1 << cm))
1271 && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1272 pr_info("%s (%x) not reported by BIOS,"
1273 " enabling anyway\n", name, 1 << cm);
1274 eeepc->cm_supported |= 1 << cm;
1275 }
1276}
1277
1278static void cmsg_quirks(struct eeepc_laptop *eeepc)
1279{
1280 cmsg_quirk(eeepc, CM_ASL_LID, "LID");
1281 cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
1282 cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
1283 cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1284}
1285
1286static int eeepc_acpi_init(struct eeepc_laptop *eeepc,
1287 struct acpi_device *device)
1288{
1289 unsigned int init_flags;
1206 int result; 1290 int result;
1207 1291
1208 if (!device) 1292 result = acpi_bus_get_status(device);
1209 return -EINVAL;
1210 pr_notice(EEEPC_HOTK_NAME "\n");
1211 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
1212 if (!ehotk)
1213 return -ENOMEM;
1214 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1215 ehotk->handle = device->handle;
1216 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
1217 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
1218 device->driver_data = ehotk;
1219 ehotk->device = device;
1220
1221 result = eeepc_hotk_check();
1222 if (result) 1293 if (result)
1223 goto fail_platform_driver; 1294 return result;
1224 eeepc_enable_camera(); 1295 if (!device->status.present) {
1296 pr_err("Hotkey device not present, aborting\n");
1297 return -ENODEV;
1298 }
1225 1299
1226 /* Register platform stuff */ 1300 init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1227 result = platform_driver_register(&platform_driver); 1301 pr_notice("Hotkey init flags 0x%x\n", init_flags);
1228 if (result) 1302
1229 goto fail_platform_driver; 1303 if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
1230 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1); 1304 pr_err("Hotkey initialization failed\n");
1231 if (!platform_device) { 1305 return -ENODEV;
1232 result = -ENOMEM;
1233 goto fail_platform_device1;
1234 } 1306 }
1235 result = platform_device_add(platform_device); 1307
1236 if (result) 1308 /* get control methods supported */
1237 goto fail_platform_device2; 1309 if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
1238 result = sysfs_create_group(&platform_device->dev.kobj, 1310 pr_err("Get control methods supported failed\n");
1239 &platform_attribute_group); 1311 return -ENODEV;
1312 }
1313 cmsg_quirks(eeepc);
1314 pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
1315
1316 return 0;
1317}
1318
1319static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc)
1320{
1321 /*
1322 * If the following call to set_acpi() fails, it's because there's no
1323 * camera so we can ignore the error.
1324 */
1325 if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
1326 set_acpi(eeepc, CM_ASL_CAMERA, 1);
1327}
1328
1329static bool eeepc_device_present;
1330
1331static int __devinit eeepc_acpi_add(struct acpi_device *device)
1332{
1333 struct eeepc_laptop *eeepc;
1334 int result;
1335
1336 pr_notice(EEEPC_LAPTOP_NAME "\n");
1337 eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
1338 if (!eeepc)
1339 return -ENOMEM;
1340 eeepc->handle = device->handle;
1341 strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1342 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1343 device->driver_data = eeepc;
1344
1345 result = eeepc_acpi_init(eeepc, device);
1240 if (result) 1346 if (result)
1241 goto fail_sysfs; 1347 goto fail_platform;
1348 eeepc_enable_camera(eeepc);
1242 1349
1243 dev = &platform_device->dev; 1350 /*
1351 * Register the platform device first. It is used as a parent for the
1352 * sub-devices below.
1353 *
1354 * Note that if there are multiple instances of this ACPI device it
1355 * will bail out, because the platform device is registered with a
1356 * fixed name. Of course it doesn't make sense to have more than one,
1357 * and machine-specific scripts find the fixed name convenient. But
1358 * It's also good for us to exclude multiple instances because both
1359 * our hwmon and our wlan rfkill subdevice use global ACPI objects
1360 * (the EC and the wlan PCI slot respectively).
1361 */
1362 result = eeepc_platform_init(eeepc);
1363 if (result)
1364 goto fail_platform;
1244 1365
1245 if (!acpi_video_backlight_support()) { 1366 if (!acpi_video_backlight_support()) {
1246 result = eeepc_backlight_init(dev); 1367 result = eeepc_backlight_init(eeepc);
1247 if (result) 1368 if (result)
1248 goto fail_backlight; 1369 goto fail_backlight;
1249 } else 1370 } else
1250 pr_info("Backlight controlled by ACPI video " 1371 pr_info("Backlight controlled by ACPI video driver\n");
1251 "driver\n");
1252 1372
1253 result = eeepc_input_init(dev); 1373 result = eeepc_input_init(eeepc);
1254 if (result) 1374 if (result)
1255 goto fail_input; 1375 goto fail_input;
1256 1376
1257 result = eeepc_hwmon_init(dev); 1377 result = eeepc_hwmon_init(eeepc);
1258 if (result) 1378 if (result)
1259 goto fail_hwmon; 1379 goto fail_hwmon;
1260 1380
1261 result = eeepc_rfkill_init(dev); 1381 result = eeepc_led_init(eeepc);
1382 if (result)
1383 goto fail_led;
1384
1385 result = eeepc_rfkill_init(eeepc);
1262 if (result) 1386 if (result)
1263 goto fail_rfkill; 1387 goto fail_rfkill;
1264 1388
1389 eeepc_device_present = true;
1265 return 0; 1390 return 0;
1266 1391
1267fail_rfkill: 1392fail_rfkill:
1268 eeepc_hwmon_exit(); 1393 eeepc_led_exit(eeepc);
1394fail_led:
1395 eeepc_hwmon_exit(eeepc);
1269fail_hwmon: 1396fail_hwmon:
1270 eeepc_input_exit(); 1397 eeepc_input_exit(eeepc);
1271fail_input: 1398fail_input:
1272 eeepc_backlight_exit(); 1399 eeepc_backlight_exit(eeepc);
1273fail_backlight: 1400fail_backlight:
1274 sysfs_remove_group(&platform_device->dev.kobj, 1401 eeepc_platform_exit(eeepc);
1275 &platform_attribute_group); 1402fail_platform:
1276fail_sysfs: 1403 kfree(eeepc);
1277 platform_device_del(platform_device);
1278fail_platform_device2:
1279 platform_device_put(platform_device);
1280fail_platform_device1:
1281 platform_driver_unregister(&platform_driver);
1282fail_platform_driver:
1283 kfree(ehotk);
1284 1404
1285 return result; 1405 return result;
1286} 1406}
1287 1407
1288static int eeepc_hotk_remove(struct acpi_device *device, int type) 1408static int eeepc_acpi_remove(struct acpi_device *device, int type)
1289{ 1409{
1290 if (!device || !acpi_driver_data(device)) 1410 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1291 return -EINVAL;
1292 1411
1293 eeepc_backlight_exit(); 1412 eeepc_backlight_exit(eeepc);
1294 eeepc_rfkill_exit(); 1413 eeepc_rfkill_exit(eeepc);
1295 eeepc_input_exit(); 1414 eeepc_input_exit(eeepc);
1296 eeepc_hwmon_exit(); 1415 eeepc_hwmon_exit(eeepc);
1297 sysfs_remove_group(&platform_device->dev.kobj, 1416 eeepc_led_exit(eeepc);
1298 &platform_attribute_group); 1417 eeepc_platform_exit(eeepc);
1299 platform_device_unregister(platform_device);
1300 platform_driver_unregister(&platform_driver);
1301 1418
1302 kfree(ehotk); 1419 kfree(eeepc);
1303 return 0; 1420 return 0;
1304} 1421}
1305 1422
1423
1424static const struct acpi_device_id eeepc_device_ids[] = {
1425 {EEEPC_ACPI_HID, 0},
1426 {"", 0},
1427};
1428MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1429
1430static struct acpi_driver eeepc_acpi_driver = {
1431 .name = EEEPC_LAPTOP_NAME,
1432 .class = EEEPC_ACPI_CLASS,
1433 .owner = THIS_MODULE,
1434 .ids = eeepc_device_ids,
1435 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1436 .ops = {
1437 .add = eeepc_acpi_add,
1438 .remove = eeepc_acpi_remove,
1439 .notify = eeepc_acpi_notify,
1440 },
1441};
1442
1443
1306static int __init eeepc_laptop_init(void) 1444static int __init eeepc_laptop_init(void)
1307{ 1445{
1308 int result; 1446 int result;
1309 1447
1310 if (acpi_disabled) 1448 result = platform_driver_register(&platform_driver);
1311 return -ENODEV;
1312 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1313 if (result < 0) 1449 if (result < 0)
1314 return result; 1450 return result;
1315 if (!ehotk) { 1451
1316 acpi_bus_unregister_driver(&eeepc_hotk_driver); 1452 result = acpi_bus_register_driver(&eeepc_acpi_driver);
1317 return -ENODEV; 1453 if (result < 0)
1454 goto fail_acpi_driver;
1455 if (!eeepc_device_present) {
1456 result = -ENODEV;
1457 goto fail_no_device;
1318 } 1458 }
1319 return 0; 1459 return 0;
1460
1461fail_no_device:
1462 acpi_bus_unregister_driver(&eeepc_acpi_driver);
1463fail_acpi_driver:
1464 platform_driver_unregister(&platform_driver);
1465 return result;
1320} 1466}
1321 1467
1322static void __exit eeepc_laptop_exit(void) 1468static void __exit eeepc_laptop_exit(void)
1323{ 1469{
1324 acpi_bus_unregister_driver(&eeepc_hotk_driver); 1470 acpi_bus_unregister_driver(&eeepc_acpi_driver);
1471 platform_driver_unregister(&platform_driver);
1325} 1472}
1326 1473
1327module_init(eeepc_laptop_init); 1474module_init(eeepc_laptop_init);
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index c2842171cec6..63c3e658a884 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -51,6 +51,12 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
51#define HPWMI_WIRELESS_QUERY 0x5 51#define HPWMI_WIRELESS_QUERY 0x5
52#define HPWMI_HOTKEY_QUERY 0xc 52#define HPWMI_HOTKEY_QUERY 0xc
53 53
54enum hp_wmi_radio {
55 HPWMI_WIFI = 0,
56 HPWMI_BLUETOOTH = 1,
57 HPWMI_WWAN = 2,
58};
59
54static int __init hp_wmi_bios_setup(struct platform_device *device); 60static int __init hp_wmi_bios_setup(struct platform_device *device);
55static int __exit hp_wmi_bios_remove(struct platform_device *device); 61static int __exit hp_wmi_bios_remove(struct platform_device *device);
56static int hp_wmi_resume_handler(struct device *device); 62static int hp_wmi_resume_handler(struct device *device);
@@ -94,7 +100,7 @@ static struct rfkill *wifi_rfkill;
94static struct rfkill *bluetooth_rfkill; 100static struct rfkill *bluetooth_rfkill;
95static struct rfkill *wwan_rfkill; 101static struct rfkill *wwan_rfkill;
96 102
97static struct dev_pm_ops hp_wmi_pm_ops = { 103static const struct dev_pm_ops hp_wmi_pm_ops = {
98 .resume = hp_wmi_resume_handler, 104 .resume = hp_wmi_resume_handler,
99 .restore = hp_wmi_resume_handler, 105 .restore = hp_wmi_resume_handler,
100}; 106};
@@ -175,8 +181,8 @@ static int hp_wmi_tablet_state(void)
175 181
176static int hp_wmi_set_block(void *data, bool blocked) 182static int hp_wmi_set_block(void *data, bool blocked)
177{ 183{
178 unsigned long b = (unsigned long) data; 184 enum hp_wmi_radio r = (enum hp_wmi_radio) data;
179 int query = BIT(b + 8) | ((!blocked) << b); 185 int query = BIT(r + 8) | ((!blocked) << r);
180 186
181 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); 187 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query);
182} 188}
@@ -185,31 +191,23 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = {
185 .set_block = hp_wmi_set_block, 191 .set_block = hp_wmi_set_block,
186}; 192};
187 193
188static bool hp_wmi_wifi_state(void) 194static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
189{
190 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
191
192 if (wireless & 0x100)
193 return false;
194 else
195 return true;
196}
197
198static bool hp_wmi_bluetooth_state(void)
199{ 195{
200 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 196 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
197 int mask = 0x200 << (r * 8);
201 198
202 if (wireless & 0x10000) 199 if (wireless & mask)
203 return false; 200 return false;
204 else 201 else
205 return true; 202 return true;
206} 203}
207 204
208static bool hp_wmi_wwan_state(void) 205static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
209{ 206{
210 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 207 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
208 int mask = 0x800 << (r * 8);
211 209
212 if (wireless & 0x1000000) 210 if (wireless & mask)
213 return false; 211 return false;
214 else 212 else
215 return true; 213 return true;
@@ -334,49 +332,55 @@ static void hp_wmi_notify(u32 value, void *context)
334 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 332 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
335 static struct key_entry *key; 333 static struct key_entry *key;
336 union acpi_object *obj; 334 union acpi_object *obj;
335 int eventcode;
337 336
338 wmi_get_event_data(value, &response); 337 wmi_get_event_data(value, &response);
339 338
340 obj = (union acpi_object *)response.pointer; 339 obj = (union acpi_object *)response.pointer;
341 340
342 if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) { 341 if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
343 int eventcode = *((u8 *) obj->buffer.pointer); 342 printk(KERN_INFO "HP WMI: Unknown response received\n");
344 if (eventcode == 0x4) 343 return;
345 eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 344 }
346 0); 345
347 key = hp_wmi_get_entry_by_scancode(eventcode); 346 eventcode = *((u8 *) obj->buffer.pointer);
348 if (key) { 347 if (eventcode == 0x4)
349 switch (key->type) { 348 eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
350 case KE_KEY: 349 0);
351 input_report_key(hp_wmi_input_dev, 350 key = hp_wmi_get_entry_by_scancode(eventcode);
352 key->keycode, 1); 351 if (key) {
353 input_sync(hp_wmi_input_dev); 352 switch (key->type) {
354 input_report_key(hp_wmi_input_dev, 353 case KE_KEY:
355 key->keycode, 0); 354 input_report_key(hp_wmi_input_dev,
356 input_sync(hp_wmi_input_dev); 355 key->keycode, 1);
357 break; 356 input_sync(hp_wmi_input_dev);
358 } 357 input_report_key(hp_wmi_input_dev,
359 } else if (eventcode == 0x1) { 358 key->keycode, 0);
360 input_report_switch(hp_wmi_input_dev, SW_DOCK,
361 hp_wmi_dock_state());
362 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
363 hp_wmi_tablet_state());
364 input_sync(hp_wmi_input_dev); 359 input_sync(hp_wmi_input_dev);
365 } else if (eventcode == 0x5) { 360 break;
366 if (wifi_rfkill) 361 }
367 rfkill_set_sw_state(wifi_rfkill, 362 } else if (eventcode == 0x1) {
368 hp_wmi_wifi_state()); 363 input_report_switch(hp_wmi_input_dev, SW_DOCK,
369 if (bluetooth_rfkill) 364 hp_wmi_dock_state());
370 rfkill_set_sw_state(bluetooth_rfkill, 365 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
371 hp_wmi_bluetooth_state()); 366 hp_wmi_tablet_state());
372 if (wwan_rfkill) 367 input_sync(hp_wmi_input_dev);
373 rfkill_set_sw_state(wwan_rfkill, 368 } else if (eventcode == 0x5) {
374 hp_wmi_wwan_state()); 369 if (wifi_rfkill)
375 } else 370 rfkill_set_states(wifi_rfkill,
376 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", 371 hp_wmi_get_sw_state(HPWMI_WIFI),
377 eventcode); 372 hp_wmi_get_hw_state(HPWMI_WIFI));
373 if (bluetooth_rfkill)
374 rfkill_set_states(bluetooth_rfkill,
375 hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
376 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
377 if (wwan_rfkill)
378 rfkill_set_states(wwan_rfkill,
379 hp_wmi_get_sw_state(HPWMI_WWAN),
380 hp_wmi_get_hw_state(HPWMI_WWAN));
378 } else 381 } else
379 printk(KERN_INFO "HP WMI: Unknown response received\n"); 382 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
383 eventcode);
380} 384}
381 385
382static int __init hp_wmi_input_setup(void) 386static int __init hp_wmi_input_setup(void)
@@ -455,7 +459,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
455 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 459 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
456 RFKILL_TYPE_WLAN, 460 RFKILL_TYPE_WLAN,
457 &hp_wmi_rfkill_ops, 461 &hp_wmi_rfkill_ops,
458 (void *) 0); 462 (void *) HPWMI_WIFI);
463 rfkill_init_sw_state(wifi_rfkill,
464 hp_wmi_get_sw_state(HPWMI_WIFI));
465 rfkill_set_hw_state(wifi_rfkill,
466 hp_wmi_get_hw_state(HPWMI_WIFI));
459 err = rfkill_register(wifi_rfkill); 467 err = rfkill_register(wifi_rfkill);
460 if (err) 468 if (err)
461 goto register_wifi_error; 469 goto register_wifi_error;
@@ -465,7 +473,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
465 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, 473 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
466 RFKILL_TYPE_BLUETOOTH, 474 RFKILL_TYPE_BLUETOOTH,
467 &hp_wmi_rfkill_ops, 475 &hp_wmi_rfkill_ops,
468 (void *) 1); 476 (void *) HPWMI_BLUETOOTH);
477 rfkill_init_sw_state(bluetooth_rfkill,
478 hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
479 rfkill_set_hw_state(bluetooth_rfkill,
480 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
469 err = rfkill_register(bluetooth_rfkill); 481 err = rfkill_register(bluetooth_rfkill);
470 if (err) 482 if (err)
471 goto register_bluetooth_error; 483 goto register_bluetooth_error;
@@ -475,7 +487,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
475 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, 487 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
476 RFKILL_TYPE_WWAN, 488 RFKILL_TYPE_WWAN,
477 &hp_wmi_rfkill_ops, 489 &hp_wmi_rfkill_ops,
478 (void *) 2); 490 (void *) HPWMI_WWAN);
491 rfkill_init_sw_state(wwan_rfkill,
492 hp_wmi_get_sw_state(HPWMI_WWAN));
493 rfkill_set_hw_state(wwan_rfkill,
494 hp_wmi_get_hw_state(HPWMI_WWAN));
479 err = rfkill_register(wwan_rfkill); 495 err = rfkill_register(wwan_rfkill);
480 if (err) 496 if (err)
481 goto register_wwan_err; 497 goto register_wwan_err;
@@ -533,6 +549,19 @@ static int hp_wmi_resume_handler(struct device *device)
533 input_sync(hp_wmi_input_dev); 549 input_sync(hp_wmi_input_dev);
534 } 550 }
535 551
552 if (wifi_rfkill)
553 rfkill_set_states(wifi_rfkill,
554 hp_wmi_get_sw_state(HPWMI_WIFI),
555 hp_wmi_get_hw_state(HPWMI_WIFI));
556 if (bluetooth_rfkill)
557 rfkill_set_states(bluetooth_rfkill,
558 hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
559 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
560 if (wwan_rfkill)
561 rfkill_set_states(wwan_rfkill,
562 hp_wmi_get_sw_state(HPWMI_WWAN),
563 hp_wmi_get_hw_state(HPWMI_WWAN));
564
536 return 0; 565 return 0;
537} 566}
538 567
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index 29432a50be45..f0a90a6bf396 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -510,7 +510,7 @@ static int __init intel_menlow_module_init(void)
510 /* Looking for sensors in each ACPI thermal zone */ 510 /* Looking for sensors in each ACPI thermal zone */
511 status = acpi_walk_namespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT, 511 status = acpi_walk_namespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT,
512 ACPI_UINT32_MAX, 512 ACPI_UINT32_MAX,
513 intel_menlow_register_sensor, NULL, NULL); 513 intel_menlow_register_sensor, NULL, NULL, NULL);
514 if (ACPI_FAILURE(status)) 514 if (ACPI_FAILURE(status))
515 return -ENODEV; 515 return -ENODEV;
516 516
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index a2a742c8ff7e..7a2cc8a5c975 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1203,7 +1203,7 @@ static int sony_nc_add(struct acpi_device *device)
1203 1203
1204 if (debug) { 1204 if (debug) {
1205 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, 1205 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
1206 1, sony_walk_callback, NULL, NULL); 1206 1, sony_walk_callback, NULL, NULL, NULL);
1207 if (ACPI_FAILURE(status)) { 1207 if (ACPI_FAILURE(status)) {
1208 printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); 1208 printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
1209 result = -ENODEV; 1209 result = -ENODEV;
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index d93108d148fc..448c8aeb166b 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -21,8 +21,8 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#define TPACPI_VERSION "0.23" 24#define TPACPI_VERSION "0.24"
25#define TPACPI_SYSFS_VERSION 0x020500 25#define TPACPI_SYSFS_VERSION 0x020700
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -61,6 +61,7 @@
61 61
62#include <linux/nvram.h> 62#include <linux/nvram.h>
63#include <linux/proc_fs.h> 63#include <linux/proc_fs.h>
64#include <linux/seq_file.h>
64#include <linux/sysfs.h> 65#include <linux/sysfs.h>
65#include <linux/backlight.h> 66#include <linux/backlight.h>
66#include <linux/fb.h> 67#include <linux/fb.h>
@@ -76,6 +77,10 @@
76#include <linux/jiffies.h> 77#include <linux/jiffies.h>
77#include <linux/workqueue.h> 78#include <linux/workqueue.h>
78 79
80#include <sound/core.h>
81#include <sound/control.h>
82#include <sound/initval.h>
83
79#include <acpi/acpi_drivers.h> 84#include <acpi/acpi_drivers.h>
80 85
81#include <linux/pci_ids.h> 86#include <linux/pci_ids.h>
@@ -231,6 +236,7 @@ enum tpacpi_hkey_event_t {
231#define TPACPI_DBG_HKEY 0x0008 236#define TPACPI_DBG_HKEY 0x0008
232#define TPACPI_DBG_FAN 0x0010 237#define TPACPI_DBG_FAN 0x0010
233#define TPACPI_DBG_BRGHT 0x0020 238#define TPACPI_DBG_BRGHT 0x0020
239#define TPACPI_DBG_MIXER 0x0040
234 240
235#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") 241#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
236#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") 242#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
@@ -256,7 +262,7 @@ struct tp_acpi_drv_struct {
256struct ibm_struct { 262struct ibm_struct {
257 char *name; 263 char *name;
258 264
259 int (*read) (char *); 265 int (*read) (struct seq_file *);
260 int (*write) (char *); 266 int (*write) (char *);
261 void (*exit) (void); 267 void (*exit) (void);
262 void (*resume) (void); 268 void (*resume) (void);
@@ -298,6 +304,7 @@ static struct {
298 u32 fan_ctrl_status_undef:1; 304 u32 fan_ctrl_status_undef:1;
299 u32 second_fan:1; 305 u32 second_fan:1;
300 u32 beep_needs_two_args:1; 306 u32 beep_needs_two_args:1;
307 u32 mixer_no_level_control:1;
301 u32 input_device_registered:1; 308 u32 input_device_registered:1;
302 u32 platform_drv_registered:1; 309 u32 platform_drv_registered:1;
303 u32 platform_drv_attrs_registered:1; 310 u32 platform_drv_attrs_registered:1;
@@ -309,6 +316,7 @@ static struct {
309 316
310static struct { 317static struct {
311 u16 hotkey_mask_ff:1; 318 u16 hotkey_mask_ff:1;
319 u16 volume_ctrl_forbidden:1;
312} tp_warned; 320} tp_warned;
313 321
314struct thinkpad_id_data { 322struct thinkpad_id_data {
@@ -425,6 +433,12 @@ static void tpacpi_log_usertask(const char * const what)
425 .ec = TPACPI_MATCH_ANY, \ 433 .ec = TPACPI_MATCH_ANY, \
426 .quirks = (__quirk) } 434 .quirks = (__quirk) }
427 435
436#define TPACPI_QEC_LNV(__id1, __id2, __quirk) \
437 { .vendor = PCI_VENDOR_ID_LENOVO, \
438 .bios = TPACPI_MATCH_ANY, \
439 .ec = TPID(__id1, __id2), \
440 .quirks = (__quirk) }
441
428struct tpacpi_quirk { 442struct tpacpi_quirk {
429 unsigned int vendor; 443 unsigned int vendor;
430 u16 bios; 444 u16 bios;
@@ -776,36 +790,25 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
776 **************************************************************************** 790 ****************************************************************************
777 ****************************************************************************/ 791 ****************************************************************************/
778 792
779static int dispatch_procfs_read(char *page, char **start, off_t off, 793static int dispatch_proc_show(struct seq_file *m, void *v)
780 int count, int *eof, void *data)
781{ 794{
782 struct ibm_struct *ibm = data; 795 struct ibm_struct *ibm = m->private;
783 int len;
784 796
785 if (!ibm || !ibm->read) 797 if (!ibm || !ibm->read)
786 return -EINVAL; 798 return -EINVAL;
799 return ibm->read(m);
800}
787 801
788 len = ibm->read(page); 802static int dispatch_proc_open(struct inode *inode, struct file *file)
789 if (len < 0) 803{
790 return len; 804 return single_open(file, dispatch_proc_show, PDE(inode)->data);
791
792 if (len <= off + count)
793 *eof = 1;
794 *start = page + off;
795 len -= off;
796 if (len > count)
797 len = count;
798 if (len < 0)
799 len = 0;
800
801 return len;
802} 805}
803 806
804static int dispatch_procfs_write(struct file *file, 807static ssize_t dispatch_proc_write(struct file *file,
805 const char __user *userbuf, 808 const char __user *userbuf,
806 unsigned long count, void *data) 809 size_t count, loff_t *pos)
807{ 810{
808 struct ibm_struct *ibm = data; 811 struct ibm_struct *ibm = PDE(file->f_path.dentry->d_inode)->data;
809 char *kernbuf; 812 char *kernbuf;
810 int ret; 813 int ret;
811 814
@@ -834,6 +837,15 @@ static int dispatch_procfs_write(struct file *file,
834 return ret; 837 return ret;
835} 838}
836 839
840static const struct file_operations dispatch_proc_fops = {
841 .owner = THIS_MODULE,
842 .open = dispatch_proc_open,
843 .read = seq_read,
844 .llseek = seq_lseek,
845 .release = single_release,
846 .write = dispatch_proc_write,
847};
848
837static char *next_cmd(char **cmds) 849static char *next_cmd(char **cmds)
838{ 850{
839 char *start = *cmds; 851 char *start = *cmds;
@@ -1006,11 +1018,8 @@ static int parse_strtoul(const char *buf,
1006{ 1018{
1007 char *endp; 1019 char *endp;
1008 1020
1009 while (*buf && isspace(*buf)) 1021 *value = simple_strtoul(skip_spaces(buf), &endp, 0);
1010 buf++; 1022 endp = skip_spaces(endp);
1011 *value = simple_strtoul(buf, &endp, 0);
1012 while (*endp && isspace(*endp))
1013 endp++;
1014 if (*endp || *value > max) 1023 if (*endp || *value > max)
1015 return -EINVAL; 1024 return -EINVAL;
1016 1025
@@ -1087,7 +1096,7 @@ static int __init tpacpi_check_std_acpi_brightness_support(void)
1087 */ 1096 */
1088 1097
1089 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, 1098 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
1090 tpacpi_acpi_walk_find_bcl, NULL, 1099 tpacpi_acpi_walk_find_bcl, NULL, NULL,
1091 &bcl_ptr); 1100 &bcl_ptr);
1092 1101
1093 if (ACPI_SUCCESS(status) && bcl_levels > 2) { 1102 if (ACPI_SUCCESS(status) && bcl_levels > 2) {
@@ -1264,6 +1273,7 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1264 struct tpacpi_rfk *atp_rfk; 1273 struct tpacpi_rfk *atp_rfk;
1265 int res; 1274 int res;
1266 bool sw_state = false; 1275 bool sw_state = false;
1276 bool hw_state;
1267 int sw_status; 1277 int sw_status;
1268 1278
1269 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); 1279 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
@@ -1298,7 +1308,8 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1298 rfkill_init_sw_state(atp_rfk->rfkill, sw_state); 1308 rfkill_init_sw_state(atp_rfk->rfkill, sw_state);
1299 } 1309 }
1300 } 1310 }
1301 rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); 1311 hw_state = tpacpi_rfk_check_hwblock_state();
1312 rfkill_set_hw_state(atp_rfk->rfkill, hw_state);
1302 1313
1303 res = rfkill_register(atp_rfk->rfkill); 1314 res = rfkill_register(atp_rfk->rfkill);
1304 if (res < 0) { 1315 if (res < 0) {
@@ -1311,6 +1322,9 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1311 } 1322 }
1312 1323
1313 tpacpi_rfkill_switches[id] = atp_rfk; 1324 tpacpi_rfkill_switches[id] = atp_rfk;
1325
1326 printk(TPACPI_INFO "rfkill switch %s: radio is %sblocked\n",
1327 name, (sw_state || hw_state) ? "" : "un");
1314 return 0; 1328 return 0;
1315} 1329}
1316 1330
@@ -1383,12 +1397,10 @@ static ssize_t tpacpi_rfk_sysfs_enable_store(const enum tpacpi_rfk_id id,
1383} 1397}
1384 1398
1385/* procfs -------------------------------------------------------------- */ 1399/* procfs -------------------------------------------------------------- */
1386static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p) 1400static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, struct seq_file *m)
1387{ 1401{
1388 int len = 0;
1389
1390 if (id >= TPACPI_RFK_SW_MAX) 1402 if (id >= TPACPI_RFK_SW_MAX)
1391 len += sprintf(p + len, "status:\t\tnot supported\n"); 1403 seq_printf(m, "status:\t\tnot supported\n");
1392 else { 1404 else {
1393 int status; 1405 int status;
1394 1406
@@ -1402,13 +1414,13 @@ static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p)
1402 return status; 1414 return status;
1403 } 1415 }
1404 1416
1405 len += sprintf(p + len, "status:\t\t%s\n", 1417 seq_printf(m, "status:\t\t%s\n",
1406 (status == TPACPI_RFK_RADIO_ON) ? 1418 (status == TPACPI_RFK_RADIO_ON) ?
1407 "enabled" : "disabled"); 1419 "enabled" : "disabled");
1408 len += sprintf(p + len, "commands:\tenable, disable\n"); 1420 seq_printf(m, "commands:\tenable, disable\n");
1409 } 1421 }
1410 1422
1411 return len; 1423 return 0;
1412} 1424}
1413 1425
1414static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf) 1426static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf)
@@ -1680,36 +1692,48 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
1680 | (__bv1) << 8 | (__bv2) } 1692 | (__bv1) << 8 | (__bv2) }
1681 1693
1682#define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \ 1694#define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \
1683 __eid1, __eid2, __ev1, __ev2) \ 1695 __eid, __ev1, __ev2) \
1684 { .vendor = (__v), \ 1696 { .vendor = (__v), \
1685 .bios = TPID(__bid1, __bid2), \ 1697 .bios = TPID(__bid1, __bid2), \
1686 .ec = TPID(__eid1, __eid2), \ 1698 .ec = __eid, \
1687 .quirks = (__ev1) << 24 | (__ev2) << 16 \ 1699 .quirks = (__ev1) << 24 | (__ev2) << 16 \
1688 | (__bv1) << 8 | (__bv2) } 1700 | (__bv1) << 8 | (__bv2) }
1689 1701
1690#define TPV_QI0(__id1, __id2, __bv1, __bv2) \ 1702#define TPV_QI0(__id1, __id2, __bv1, __bv2) \
1691 TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2) 1703 TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2)
1692 1704
1705/* Outdated IBM BIOSes often lack the EC id string */
1693#define TPV_QI1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \ 1706#define TPV_QI1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \
1694 TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \ 1707 TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \
1695 __bv1, __bv2, __id1, __id2, __ev1, __ev2) 1708 __bv1, __bv2, TPID(__id1, __id2), \
1709 __ev1, __ev2), \
1710 TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \
1711 __bv1, __bv2, TPACPI_MATCH_UNKNOWN, \
1712 __ev1, __ev2)
1696 1713
1714/* Outdated IBM BIOSes often lack the EC id string */
1697#define TPV_QI2(__bid1, __bid2, __bv1, __bv2, \ 1715#define TPV_QI2(__bid1, __bid2, __bv1, __bv2, \
1698 __eid1, __eid2, __ev1, __ev2) \ 1716 __eid1, __eid2, __ev1, __ev2) \
1699 TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \ 1717 TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \
1700 __bv1, __bv2, __eid1, __eid2, __ev1, __ev2) 1718 __bv1, __bv2, TPID(__eid1, __eid2), \
1719 __ev1, __ev2), \
1720 TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \
1721 __bv1, __bv2, TPACPI_MATCH_UNKNOWN, \
1722 __ev1, __ev2)
1701 1723
1702#define TPV_QL0(__id1, __id2, __bv1, __bv2) \ 1724#define TPV_QL0(__id1, __id2, __bv1, __bv2) \
1703 TPV_Q(PCI_VENDOR_ID_LENOVO, __id1, __id2, __bv1, __bv2) 1725 TPV_Q(PCI_VENDOR_ID_LENOVO, __id1, __id2, __bv1, __bv2)
1704 1726
1705#define TPV_QL1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \ 1727#define TPV_QL1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \
1706 TPV_Q_X(PCI_VENDOR_ID_LENOVO, __id1, __id2, \ 1728 TPV_Q_X(PCI_VENDOR_ID_LENOVO, __id1, __id2, \
1707 __bv1, __bv2, __id1, __id2, __ev1, __ev2) 1729 __bv1, __bv2, TPID(__id1, __id2), \
1730 __ev1, __ev2)
1708 1731
1709#define TPV_QL2(__bid1, __bid2, __bv1, __bv2, \ 1732#define TPV_QL2(__bid1, __bid2, __bv1, __bv2, \
1710 __eid1, __eid2, __ev1, __ev2) \ 1733 __eid1, __eid2, __ev1, __ev2) \
1711 TPV_Q_X(PCI_VENDOR_ID_LENOVO, __bid1, __bid2, \ 1734 TPV_Q_X(PCI_VENDOR_ID_LENOVO, __bid1, __bid2, \
1712 __bv1, __bv2, __eid1, __eid2, __ev1, __ev2) 1735 __bv1, __bv2, TPID(__eid1, __eid2), \
1736 __ev1, __ev2)
1713 1737
1714static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = { 1738static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1715 /* Numeric models ------------------ */ 1739 /* Numeric models ------------------ */
@@ -1767,7 +1791,7 @@ static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1767 1791
1768 TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */ 1792 TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */
1769 TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */ 1793 TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */
1770 TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */ 1794 TPV_QL1('7', 'E', 'D', '0', '1', '5'), /* R60e, R60i */
1771 1795
1772 /* BIOS FW BIOS VERS EC FW EC VERS */ 1796 /* BIOS FW BIOS VERS EC FW EC VERS */
1773 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */ 1797 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */
@@ -1783,8 +1807,8 @@ static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1783 TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */ 1807 TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */
1784 TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */ 1808 TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */
1785 1809
1786 TPV_QL0('7', 'B', 'D', '7'), /* X60/s */ 1810 TPV_QL1('7', 'B', 'D', '7', '4', '0'), /* X60/s */
1787 TPV_QL0('7', 'J', '3', '0'), /* X60t */ 1811 TPV_QL1('7', 'J', '3', '0', '1', '3'), /* X60t */
1788 1812
1789 /* (0) - older versions lack DMI EC fw string and functionality */ 1813 /* (0) - older versions lack DMI EC fw string and functionality */
1790 /* (1) - older versions known to lack functionality */ 1814 /* (1) - older versions known to lack functionality */
@@ -1874,14 +1898,11 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
1874 return 0; 1898 return 0;
1875} 1899}
1876 1900
1877static int thinkpad_acpi_driver_read(char *p) 1901static int thinkpad_acpi_driver_read(struct seq_file *m)
1878{ 1902{
1879 int len = 0; 1903 seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC);
1880 1904 seq_printf(m, "version:\t%s\n", TPACPI_VERSION);
1881 len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC); 1905 return 0;
1882 len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION);
1883
1884 return len;
1885} 1906}
1886 1907
1887static struct ibm_struct thinkpad_acpi_driver_data = { 1908static struct ibm_struct thinkpad_acpi_driver_data = {
@@ -2177,7 +2198,8 @@ static int hotkey_mask_set(u32 mask)
2177 fwmask, hotkey_acpi_mask); 2198 fwmask, hotkey_acpi_mask);
2178 } 2199 }
2179 2200
2180 hotkey_mask_warn_incomplete_mask(); 2201 if (tpacpi_lifecycle != TPACPI_LIFE_EXITING)
2202 hotkey_mask_warn_incomplete_mask();
2181 2203
2182 return rc; 2204 return rc;
2183} 2205}
@@ -3173,6 +3195,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3173 int res, i; 3195 int res, i;
3174 int status; 3196 int status;
3175 int hkeyv; 3197 int hkeyv;
3198 bool radiosw_state = false;
3199 bool tabletsw_state = false;
3176 3200
3177 unsigned long quirks; 3201 unsigned long quirks;
3178 3202
@@ -3278,6 +3302,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3278#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3302#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3279 if (dbg_wlswemul) { 3303 if (dbg_wlswemul) {
3280 tp_features.hotkey_wlsw = 1; 3304 tp_features.hotkey_wlsw = 1;
3305 radiosw_state = !!tpacpi_wlsw_emulstate;
3281 printk(TPACPI_INFO 3306 printk(TPACPI_INFO
3282 "radio switch emulation enabled\n"); 3307 "radio switch emulation enabled\n");
3283 } else 3308 } else
@@ -3285,6 +3310,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3285 /* Not all thinkpads have a hardware radio switch */ 3310 /* Not all thinkpads have a hardware radio switch */
3286 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { 3311 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
3287 tp_features.hotkey_wlsw = 1; 3312 tp_features.hotkey_wlsw = 1;
3313 radiosw_state = !!status;
3288 printk(TPACPI_INFO 3314 printk(TPACPI_INFO
3289 "radio switch found; radios are %s\n", 3315 "radio switch found; radios are %s\n",
3290 enabled(status, 0)); 3316 enabled(status, 0));
@@ -3296,11 +3322,11 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3296 /* For X41t, X60t, X61t Tablets... */ 3322 /* For X41t, X60t, X61t Tablets... */
3297 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { 3323 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
3298 tp_features.hotkey_tablet = 1; 3324 tp_features.hotkey_tablet = 1;
3325 tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK);
3299 printk(TPACPI_INFO 3326 printk(TPACPI_INFO
3300 "possible tablet mode switch found; " 3327 "possible tablet mode switch found; "
3301 "ThinkPad in %s mode\n", 3328 "ThinkPad in %s mode\n",
3302 (status & TP_HOTKEY_TABLET_MASK)? 3329 (tabletsw_state) ? "tablet" : "laptop");
3303 "tablet" : "laptop");
3304 res = add_to_attr_set(hotkey_dev_attributes, 3330 res = add_to_attr_set(hotkey_dev_attributes,
3305 &dev_attr_hotkey_tablet_mode.attr); 3331 &dev_attr_hotkey_tablet_mode.attr);
3306 } 3332 }
@@ -3335,16 +3361,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3335 TPACPI_HOTKEY_MAP_SIZE); 3361 TPACPI_HOTKEY_MAP_SIZE);
3336 } 3362 }
3337 3363
3338 set_bit(EV_KEY, tpacpi_inputdev->evbit); 3364 input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
3339 set_bit(EV_MSC, tpacpi_inputdev->evbit);
3340 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
3341 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; 3365 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
3342 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; 3366 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
3343 tpacpi_inputdev->keycode = hotkey_keycode_map; 3367 tpacpi_inputdev->keycode = hotkey_keycode_map;
3344 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { 3368 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
3345 if (hotkey_keycode_map[i] != KEY_RESERVED) { 3369 if (hotkey_keycode_map[i] != KEY_RESERVED) {
3346 set_bit(hotkey_keycode_map[i], 3370 input_set_capability(tpacpi_inputdev, EV_KEY,
3347 tpacpi_inputdev->keybit); 3371 hotkey_keycode_map[i]);
3348 } else { 3372 } else {
3349 if (i < sizeof(hotkey_reserved_mask)*8) 3373 if (i < sizeof(hotkey_reserved_mask)*8)
3350 hotkey_reserved_mask |= 1 << i; 3374 hotkey_reserved_mask |= 1 << i;
@@ -3352,12 +3376,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3352 } 3376 }
3353 3377
3354 if (tp_features.hotkey_wlsw) { 3378 if (tp_features.hotkey_wlsw) {
3355 set_bit(EV_SW, tpacpi_inputdev->evbit); 3379 input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL);
3356 set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); 3380 input_report_switch(tpacpi_inputdev,
3381 SW_RFKILL_ALL, radiosw_state);
3357 } 3382 }
3358 if (tp_features.hotkey_tablet) { 3383 if (tp_features.hotkey_tablet) {
3359 set_bit(EV_SW, tpacpi_inputdev->evbit); 3384 input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE);
3360 set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); 3385 input_report_switch(tpacpi_inputdev,
3386 SW_TABLET_MODE, tabletsw_state);
3361 } 3387 }
3362 3388
3363 /* Do not issue duplicate brightness change events to 3389 /* Do not issue duplicate brightness change events to
@@ -3424,8 +3450,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3424 tpacpi_inputdev->close = &hotkey_inputdev_close; 3450 tpacpi_inputdev->close = &hotkey_inputdev_close;
3425 3451
3426 hotkey_poll_setup_safe(true); 3452 hotkey_poll_setup_safe(true);
3427 tpacpi_send_radiosw_update();
3428 tpacpi_input_send_tabletsw();
3429 3453
3430 return 0; 3454 return 0;
3431 3455
@@ -3533,49 +3557,57 @@ static bool hotkey_notify_usrevent(const u32 hkey,
3533 } 3557 }
3534} 3558}
3535 3559
3560static void thermal_dump_all_sensors(void);
3561
3536static bool hotkey_notify_thermal(const u32 hkey, 3562static bool hotkey_notify_thermal(const u32 hkey,
3537 bool *send_acpi_ev, 3563 bool *send_acpi_ev,
3538 bool *ignore_acpi_ev) 3564 bool *ignore_acpi_ev)
3539{ 3565{
3566 bool known = true;
3567
3540 /* 0x6000-0x6FFF: thermal alarms */ 3568 /* 0x6000-0x6FFF: thermal alarms */
3541 *send_acpi_ev = true; 3569 *send_acpi_ev = true;
3542 *ignore_acpi_ev = false; 3570 *ignore_acpi_ev = false;
3543 3571
3544 switch (hkey) { 3572 switch (hkey) {
3573 case TP_HKEY_EV_THM_TABLE_CHANGED:
3574 printk(TPACPI_INFO
3575 "EC reports that Thermal Table has changed\n");
3576 /* recommended action: do nothing, we don't have
3577 * Lenovo ATM information */
3578 return true;
3545 case TP_HKEY_EV_ALARM_BAT_HOT: 3579 case TP_HKEY_EV_ALARM_BAT_HOT:
3546 printk(TPACPI_CRIT 3580 printk(TPACPI_CRIT
3547 "THERMAL ALARM: battery is too hot!\n"); 3581 "THERMAL ALARM: battery is too hot!\n");
3548 /* recommended action: warn user through gui */ 3582 /* recommended action: warn user through gui */
3549 return true; 3583 break;
3550 case TP_HKEY_EV_ALARM_BAT_XHOT: 3584 case TP_HKEY_EV_ALARM_BAT_XHOT:
3551 printk(TPACPI_ALERT 3585 printk(TPACPI_ALERT
3552 "THERMAL EMERGENCY: battery is extremely hot!\n"); 3586 "THERMAL EMERGENCY: battery is extremely hot!\n");
3553 /* recommended action: immediate sleep/hibernate */ 3587 /* recommended action: immediate sleep/hibernate */
3554 return true; 3588 break;
3555 case TP_HKEY_EV_ALARM_SENSOR_HOT: 3589 case TP_HKEY_EV_ALARM_SENSOR_HOT:
3556 printk(TPACPI_CRIT 3590 printk(TPACPI_CRIT
3557 "THERMAL ALARM: " 3591 "THERMAL ALARM: "
3558 "a sensor reports something is too hot!\n"); 3592 "a sensor reports something is too hot!\n");
3559 /* recommended action: warn user through gui, that */ 3593 /* recommended action: warn user through gui, that */
3560 /* some internal component is too hot */ 3594 /* some internal component is too hot */
3561 return true; 3595 break;
3562 case TP_HKEY_EV_ALARM_SENSOR_XHOT: 3596 case TP_HKEY_EV_ALARM_SENSOR_XHOT:
3563 printk(TPACPI_ALERT 3597 printk(TPACPI_ALERT
3564 "THERMAL EMERGENCY: " 3598 "THERMAL EMERGENCY: "
3565 "a sensor reports something is extremely hot!\n"); 3599 "a sensor reports something is extremely hot!\n");
3566 /* recommended action: immediate sleep/hibernate */ 3600 /* recommended action: immediate sleep/hibernate */
3567 return true; 3601 break;
3568 case TP_HKEY_EV_THM_TABLE_CHANGED:
3569 printk(TPACPI_INFO
3570 "EC reports that Thermal Table has changed\n");
3571 /* recommended action: do nothing, we don't have
3572 * Lenovo ATM information */
3573 return true;
3574 default: 3602 default:
3575 printk(TPACPI_ALERT 3603 printk(TPACPI_ALERT
3576 "THERMAL ALERT: unknown thermal alarm received\n"); 3604 "THERMAL ALERT: unknown thermal alarm received\n");
3577 return false; 3605 known = false;
3578 } 3606 }
3607
3608 thermal_dump_all_sensors();
3609
3610 return known;
3579} 3611}
3580 3612
3581static void hotkey_notify(struct ibm_struct *ibm, u32 event) 3613static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -3718,14 +3750,13 @@ static void hotkey_resume(void)
3718} 3750}
3719 3751
3720/* procfs -------------------------------------------------------------- */ 3752/* procfs -------------------------------------------------------------- */
3721static int hotkey_read(char *p) 3753static int hotkey_read(struct seq_file *m)
3722{ 3754{
3723 int res, status; 3755 int res, status;
3724 int len = 0;
3725 3756
3726 if (!tp_features.hotkey) { 3757 if (!tp_features.hotkey) {
3727 len += sprintf(p + len, "status:\t\tnot supported\n"); 3758 seq_printf(m, "status:\t\tnot supported\n");
3728 return len; 3759 return 0;
3729 } 3760 }
3730 3761
3731 if (mutex_lock_killable(&hotkey_mutex)) 3762 if (mutex_lock_killable(&hotkey_mutex))
@@ -3737,17 +3768,16 @@ static int hotkey_read(char *p)
3737 if (res) 3768 if (res)
3738 return res; 3769 return res;
3739 3770
3740 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); 3771 seq_printf(m, "status:\t\t%s\n", enabled(status, 0));
3741 if (hotkey_all_mask) { 3772 if (hotkey_all_mask) {
3742 len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_user_mask); 3773 seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask);
3743 len += sprintf(p + len, 3774 seq_printf(m, "commands:\tenable, disable, reset, <mask>\n");
3744 "commands:\tenable, disable, reset, <mask>\n");
3745 } else { 3775 } else {
3746 len += sprintf(p + len, "mask:\t\tnot supported\n"); 3776 seq_printf(m, "mask:\t\tnot supported\n");
3747 len += sprintf(p + len, "commands:\tenable, disable, reset\n"); 3777 seq_printf(m, "commands:\tenable, disable, reset\n");
3748 } 3778 }
3749 3779
3750 return len; 3780 return 0;
3751} 3781}
3752 3782
3753static void hotkey_enabledisable_warn(bool enable) 3783static void hotkey_enabledisable_warn(bool enable)
@@ -3854,15 +3884,6 @@ enum {
3854 3884
3855#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" 3885#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw"
3856 3886
3857static void bluetooth_suspend(pm_message_t state)
3858{
3859 /* Try to make sure radio will resume powered off */
3860 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
3861 TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
3862 vdbg_printk(TPACPI_DBG_RFKILL,
3863 "bluetooth power down on resume request failed\n");
3864}
3865
3866static int bluetooth_get_status(void) 3887static int bluetooth_get_status(void)
3867{ 3888{
3868 int status; 3889 int status;
@@ -3896,10 +3917,9 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state)
3896#endif 3917#endif
3897 3918
3898 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ 3919 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
3920 status = TP_ACPI_BLUETOOTH_RESUMECTRL;
3899 if (state == TPACPI_RFK_RADIO_ON) 3921 if (state == TPACPI_RFK_RADIO_ON)
3900 status = TP_ACPI_BLUETOOTH_RADIOSSW; 3922 status |= TP_ACPI_BLUETOOTH_RADIOSSW;
3901 else
3902 status = 0;
3903 3923
3904 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 3924 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
3905 return -EIO; 3925 return -EIO;
@@ -4023,9 +4043,9 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
4023} 4043}
4024 4044
4025/* procfs -------------------------------------------------------------- */ 4045/* procfs -------------------------------------------------------------- */
4026static int bluetooth_read(char *p) 4046static int bluetooth_read(struct seq_file *m)
4027{ 4047{
4028 return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p); 4048 return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, m);
4029} 4049}
4030 4050
4031static int bluetooth_write(char *buf) 4051static int bluetooth_write(char *buf)
@@ -4038,7 +4058,6 @@ static struct ibm_struct bluetooth_driver_data = {
4038 .read = bluetooth_read, 4058 .read = bluetooth_read,
4039 .write = bluetooth_write, 4059 .write = bluetooth_write,
4040 .exit = bluetooth_exit, 4060 .exit = bluetooth_exit,
4041 .suspend = bluetooth_suspend,
4042 .shutdown = bluetooth_shutdown, 4061 .shutdown = bluetooth_shutdown,
4043}; 4062};
4044 4063
@@ -4056,15 +4075,6 @@ enum {
4056 4075
4057#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" 4076#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
4058 4077
4059static void wan_suspend(pm_message_t state)
4060{
4061 /* Try to make sure radio will resume powered off */
4062 if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
4063 TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
4064 vdbg_printk(TPACPI_DBG_RFKILL,
4065 "WWAN power down on resume request failed\n");
4066}
4067
4068static int wan_get_status(void) 4078static int wan_get_status(void)
4069{ 4079{
4070 int status; 4080 int status;
@@ -4097,11 +4107,10 @@ static int wan_set_status(enum tpacpi_rfkill_state state)
4097 } 4107 }
4098#endif 4108#endif
4099 4109
4100 /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */ 4110 /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
4111 status = TP_ACPI_WANCARD_RESUMECTRL;
4101 if (state == TPACPI_RFK_RADIO_ON) 4112 if (state == TPACPI_RFK_RADIO_ON)
4102 status = TP_ACPI_WANCARD_RADIOSSW; 4113 status |= TP_ACPI_WANCARD_RADIOSSW;
4103 else
4104 status = 0;
4105 4114
4106 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 4115 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
4107 return -EIO; 4116 return -EIO;
@@ -4224,9 +4233,9 @@ static int __init wan_init(struct ibm_init_struct *iibm)
4224} 4233}
4225 4234
4226/* procfs -------------------------------------------------------------- */ 4235/* procfs -------------------------------------------------------------- */
4227static int wan_read(char *p) 4236static int wan_read(struct seq_file *m)
4228{ 4237{
4229 return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p); 4238 return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, m);
4230} 4239}
4231 4240
4232static int wan_write(char *buf) 4241static int wan_write(char *buf)
@@ -4239,7 +4248,6 @@ static struct ibm_struct wan_driver_data = {
4239 .read = wan_read, 4248 .read = wan_read,
4240 .write = wan_write, 4249 .write = wan_write,
4241 .exit = wan_exit, 4250 .exit = wan_exit,
4242 .suspend = wan_suspend,
4243 .shutdown = wan_shutdown, 4251 .shutdown = wan_shutdown,
4244}; 4252};
4245 4253
@@ -4602,14 +4610,13 @@ static int video_expand_toggle(void)
4602 /* not reached */ 4610 /* not reached */
4603} 4611}
4604 4612
4605static int video_read(char *p) 4613static int video_read(struct seq_file *m)
4606{ 4614{
4607 int status, autosw; 4615 int status, autosw;
4608 int len = 0;
4609 4616
4610 if (video_supported == TPACPI_VIDEO_NONE) { 4617 if (video_supported == TPACPI_VIDEO_NONE) {
4611 len += sprintf(p + len, "status:\t\tnot supported\n"); 4618 seq_printf(m, "status:\t\tnot supported\n");
4612 return len; 4619 return 0;
4613 } 4620 }
4614 4621
4615 status = video_outputsw_get(); 4622 status = video_outputsw_get();
@@ -4620,20 +4627,20 @@ static int video_read(char *p)
4620 if (autosw < 0) 4627 if (autosw < 0)
4621 return autosw; 4628 return autosw;
4622 4629
4623 len += sprintf(p + len, "status:\t\tsupported\n"); 4630 seq_printf(m, "status:\t\tsupported\n");
4624 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0)); 4631 seq_printf(m, "lcd:\t\t%s\n", enabled(status, 0));
4625 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1)); 4632 seq_printf(m, "crt:\t\t%s\n", enabled(status, 1));
4626 if (video_supported == TPACPI_VIDEO_NEW) 4633 if (video_supported == TPACPI_VIDEO_NEW)
4627 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3)); 4634 seq_printf(m, "dvi:\t\t%s\n", enabled(status, 3));
4628 len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0)); 4635 seq_printf(m, "auto:\t\t%s\n", enabled(autosw, 0));
4629 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n"); 4636 seq_printf(m, "commands:\tlcd_enable, lcd_disable\n");
4630 len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n"); 4637 seq_printf(m, "commands:\tcrt_enable, crt_disable\n");
4631 if (video_supported == TPACPI_VIDEO_NEW) 4638 if (video_supported == TPACPI_VIDEO_NEW)
4632 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n"); 4639 seq_printf(m, "commands:\tdvi_enable, dvi_disable\n");
4633 len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n"); 4640 seq_printf(m, "commands:\tauto_enable, auto_disable\n");
4634 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n"); 4641 seq_printf(m, "commands:\tvideo_switch, expand_toggle\n");
4635 4642
4636 return len; 4643 return 0;
4637} 4644}
4638 4645
4639static int video_write(char *buf) 4646static int video_write(char *buf)
@@ -4825,25 +4832,24 @@ static void light_exit(void)
4825 flush_workqueue(tpacpi_wq); 4832 flush_workqueue(tpacpi_wq);
4826} 4833}
4827 4834
4828static int light_read(char *p) 4835static int light_read(struct seq_file *m)
4829{ 4836{
4830 int len = 0;
4831 int status; 4837 int status;
4832 4838
4833 if (!tp_features.light) { 4839 if (!tp_features.light) {
4834 len += sprintf(p + len, "status:\t\tnot supported\n"); 4840 seq_printf(m, "status:\t\tnot supported\n");
4835 } else if (!tp_features.light_status) { 4841 } else if (!tp_features.light_status) {
4836 len += sprintf(p + len, "status:\t\tunknown\n"); 4842 seq_printf(m, "status:\t\tunknown\n");
4837 len += sprintf(p + len, "commands:\ton, off\n"); 4843 seq_printf(m, "commands:\ton, off\n");
4838 } else { 4844 } else {
4839 status = light_get_status(); 4845 status = light_get_status();
4840 if (status < 0) 4846 if (status < 0)
4841 return status; 4847 return status;
4842 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); 4848 seq_printf(m, "status:\t\t%s\n", onoff(status, 0));
4843 len += sprintf(p + len, "commands:\ton, off\n"); 4849 seq_printf(m, "commands:\ton, off\n");
4844 } 4850 }
4845 4851
4846 return len; 4852 return 0;
4847} 4853}
4848 4854
4849static int light_write(char *buf) 4855static int light_write(char *buf)
@@ -4921,20 +4927,18 @@ static void cmos_exit(void)
4921 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command); 4927 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
4922} 4928}
4923 4929
4924static int cmos_read(char *p) 4930static int cmos_read(struct seq_file *m)
4925{ 4931{
4926 int len = 0;
4927
4928 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, 4932 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
4929 R30, R31, T20-22, X20-21 */ 4933 R30, R31, T20-22, X20-21 */
4930 if (!cmos_handle) 4934 if (!cmos_handle)
4931 len += sprintf(p + len, "status:\t\tnot supported\n"); 4935 seq_printf(m, "status:\t\tnot supported\n");
4932 else { 4936 else {
4933 len += sprintf(p + len, "status:\t\tsupported\n"); 4937 seq_printf(m, "status:\t\tsupported\n");
4934 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n"); 4938 seq_printf(m, "commands:\t<cmd> (<cmd> is 0-21)\n");
4935 } 4939 }
4936 4940
4937 return len; 4941 return 0;
4938} 4942}
4939 4943
4940static int cmos_write(char *buf) 4944static int cmos_write(char *buf)
@@ -5309,15 +5313,13 @@ static int __init led_init(struct ibm_init_struct *iibm)
5309 ((s) == TPACPI_LED_OFF ? "off" : \ 5313 ((s) == TPACPI_LED_OFF ? "off" : \
5310 ((s) == TPACPI_LED_ON ? "on" : "blinking")) 5314 ((s) == TPACPI_LED_ON ? "on" : "blinking"))
5311 5315
5312static int led_read(char *p) 5316static int led_read(struct seq_file *m)
5313{ 5317{
5314 int len = 0;
5315
5316 if (!led_supported) { 5318 if (!led_supported) {
5317 len += sprintf(p + len, "status:\t\tnot supported\n"); 5319 seq_printf(m, "status:\t\tnot supported\n");
5318 return len; 5320 return 0;
5319 } 5321 }
5320 len += sprintf(p + len, "status:\t\tsupported\n"); 5322 seq_printf(m, "status:\t\tsupported\n");
5321 5323
5322 if (led_supported == TPACPI_LED_570) { 5324 if (led_supported == TPACPI_LED_570) {
5323 /* 570 */ 5325 /* 570 */
@@ -5326,15 +5328,15 @@ static int led_read(char *p)
5326 status = led_get_status(i); 5328 status = led_get_status(i);
5327 if (status < 0) 5329 if (status < 0)
5328 return -EIO; 5330 return -EIO;
5329 len += sprintf(p + len, "%d:\t\t%s\n", 5331 seq_printf(m, "%d:\t\t%s\n",
5330 i, str_led_status(status)); 5332 i, str_led_status(status));
5331 } 5333 }
5332 } 5334 }
5333 5335
5334 len += sprintf(p + len, "commands:\t" 5336 seq_printf(m, "commands:\t"
5335 "<led> on, <led> off, <led> blink (<led> is 0-15)\n"); 5337 "<led> on, <led> off, <led> blink (<led> is 0-15)\n");
5336 5338
5337 return len; 5339 return 0;
5338} 5340}
5339 5341
5340static int led_write(char *buf) 5342static int led_write(char *buf)
@@ -5407,18 +5409,16 @@ static int __init beep_init(struct ibm_init_struct *iibm)
5407 return (beep_handle)? 0 : 1; 5409 return (beep_handle)? 0 : 1;
5408} 5410}
5409 5411
5410static int beep_read(char *p) 5412static int beep_read(struct seq_file *m)
5411{ 5413{
5412 int len = 0;
5413
5414 if (!beep_handle) 5414 if (!beep_handle)
5415 len += sprintf(p + len, "status:\t\tnot supported\n"); 5415 seq_printf(m, "status:\t\tnot supported\n");
5416 else { 5416 else {
5417 len += sprintf(p + len, "status:\t\tsupported\n"); 5417 seq_printf(m, "status:\t\tsupported\n");
5418 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n"); 5418 seq_printf(m, "commands:\t<cmd> (<cmd> is 0-17)\n");
5419 } 5419 }
5420 5420
5421 return len; 5421 return 0;
5422} 5422}
5423 5423
5424static int beep_write(char *buf) 5424static int beep_write(char *buf)
@@ -5471,8 +5471,11 @@ enum { /* TPACPI_THERMAL_TPEC_* */
5471 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */ 5471 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */
5472 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */ 5472 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */
5473 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */ 5473 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */
5474
5475 TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */
5474}; 5476};
5475 5477
5478
5476#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */ 5479#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
5477struct ibm_thermal_sensors_struct { 5480struct ibm_thermal_sensors_struct {
5478 s32 temp[TPACPI_MAX_THERMAL_SENSORS]; 5481 s32 temp[TPACPI_MAX_THERMAL_SENSORS];
@@ -5562,6 +5565,28 @@ static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
5562 return n; 5565 return n;
5563} 5566}
5564 5567
5568static void thermal_dump_all_sensors(void)
5569{
5570 int n, i;
5571 struct ibm_thermal_sensors_struct t;
5572
5573 n = thermal_get_sensors(&t);
5574 if (n <= 0)
5575 return;
5576
5577 printk(TPACPI_NOTICE
5578 "temperatures (Celsius):");
5579
5580 for (i = 0; i < n; i++) {
5581 if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA)
5582 printk(KERN_CONT " %d", (int)(t.temp[i] / 1000));
5583 else
5584 printk(KERN_CONT " N/A");
5585 }
5586
5587 printk(KERN_CONT "\n");
5588}
5589
5565/* sysfs temp##_input -------------------------------------------------- */ 5590/* sysfs temp##_input -------------------------------------------------- */
5566 5591
5567static ssize_t thermal_temp_input_show(struct device *dev, 5592static ssize_t thermal_temp_input_show(struct device *dev,
@@ -5577,7 +5602,7 @@ static ssize_t thermal_temp_input_show(struct device *dev,
5577 res = thermal_get_sensor(idx, &value); 5602 res = thermal_get_sensor(idx, &value);
5578 if (res) 5603 if (res)
5579 return res; 5604 return res;
5580 if (value == TP_EC_THERMAL_TMP_NA * 1000) 5605 if (value == TPACPI_THERMAL_SENSOR_NA)
5581 return -ENXIO; 5606 return -ENXIO;
5582 5607
5583 return snprintf(buf, PAGE_SIZE, "%d\n", value); 5608 return snprintf(buf, PAGE_SIZE, "%d\n", value);
@@ -5754,9 +5779,8 @@ static void thermal_exit(void)
5754 } 5779 }
5755} 5780}
5756 5781
5757static int thermal_read(char *p) 5782static int thermal_read(struct seq_file *m)
5758{ 5783{
5759 int len = 0;
5760 int n, i; 5784 int n, i;
5761 struct ibm_thermal_sensors_struct t; 5785 struct ibm_thermal_sensors_struct t;
5762 5786
@@ -5764,16 +5788,16 @@ static int thermal_read(char *p)
5764 if (unlikely(n < 0)) 5788 if (unlikely(n < 0))
5765 return n; 5789 return n;
5766 5790
5767 len += sprintf(p + len, "temperatures:\t"); 5791 seq_printf(m, "temperatures:\t");
5768 5792
5769 if (n > 0) { 5793 if (n > 0) {
5770 for (i = 0; i < (n - 1); i++) 5794 for (i = 0; i < (n - 1); i++)
5771 len += sprintf(p + len, "%d ", t.temp[i] / 1000); 5795 seq_printf(m, "%d ", t.temp[i] / 1000);
5772 len += sprintf(p + len, "%d\n", t.temp[i] / 1000); 5796 seq_printf(m, "%d\n", t.temp[i] / 1000);
5773 } else 5797 } else
5774 len += sprintf(p + len, "not supported\n"); 5798 seq_printf(m, "not supported\n");
5775 5799
5776 return len; 5800 return 0;
5777} 5801}
5778 5802
5779static struct ibm_struct thermal_driver_data = { 5803static struct ibm_struct thermal_driver_data = {
@@ -5788,39 +5812,38 @@ static struct ibm_struct thermal_driver_data = {
5788 5812
5789static u8 ecdump_regs[256]; 5813static u8 ecdump_regs[256];
5790 5814
5791static int ecdump_read(char *p) 5815static int ecdump_read(struct seq_file *m)
5792{ 5816{
5793 int len = 0;
5794 int i, j; 5817 int i, j;
5795 u8 v; 5818 u8 v;
5796 5819
5797 len += sprintf(p + len, "EC " 5820 seq_printf(m, "EC "
5798 " +00 +01 +02 +03 +04 +05 +06 +07" 5821 " +00 +01 +02 +03 +04 +05 +06 +07"
5799 " +08 +09 +0a +0b +0c +0d +0e +0f\n"); 5822 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
5800 for (i = 0; i < 256; i += 16) { 5823 for (i = 0; i < 256; i += 16) {
5801 len += sprintf(p + len, "EC 0x%02x:", i); 5824 seq_printf(m, "EC 0x%02x:", i);
5802 for (j = 0; j < 16; j++) { 5825 for (j = 0; j < 16; j++) {
5803 if (!acpi_ec_read(i + j, &v)) 5826 if (!acpi_ec_read(i + j, &v))
5804 break; 5827 break;
5805 if (v != ecdump_regs[i + j]) 5828 if (v != ecdump_regs[i + j])
5806 len += sprintf(p + len, " *%02x", v); 5829 seq_printf(m, " *%02x", v);
5807 else 5830 else
5808 len += sprintf(p + len, " %02x", v); 5831 seq_printf(m, " %02x", v);
5809 ecdump_regs[i + j] = v; 5832 ecdump_regs[i + j] = v;
5810 } 5833 }
5811 len += sprintf(p + len, "\n"); 5834 seq_putc(m, '\n');
5812 if (j != 16) 5835 if (j != 16)
5813 break; 5836 break;
5814 } 5837 }
5815 5838
5816 /* These are way too dangerous to advertise openly... */ 5839 /* These are way too dangerous to advertise openly... */
5817#if 0 5840#if 0
5818 len += sprintf(p + len, "commands:\t0x<offset> 0x<value>" 5841 seq_printf(m, "commands:\t0x<offset> 0x<value>"
5819 " (<offset> is 00-ff, <value> is 00-ff)\n"); 5842 " (<offset> is 00-ff, <value> is 00-ff)\n");
5820 len += sprintf(p + len, "commands:\t0x<offset> <value> " 5843 seq_printf(m, "commands:\t0x<offset> <value> "
5821 " (<offset> is 00-ff, <value> is 0-255)\n"); 5844 " (<offset> is 00-ff, <value> is 0-255)\n");
5822#endif 5845#endif
5823 return len; 5846 return 0;
5824} 5847}
5825 5848
5826static int ecdump_write(char *buf) 5849static int ecdump_write(char *buf)
@@ -6083,6 +6106,12 @@ static int brightness_get(struct backlight_device *bd)
6083 return status & TP_EC_BACKLIGHT_LVLMSK; 6106 return status & TP_EC_BACKLIGHT_LVLMSK;
6084} 6107}
6085 6108
6109static void tpacpi_brightness_notify_change(void)
6110{
6111 backlight_force_update(ibm_backlight_device,
6112 BACKLIGHT_UPDATE_HOTKEY);
6113}
6114
6086static struct backlight_ops ibm_backlight_data = { 6115static struct backlight_ops ibm_backlight_data = {
6087 .get_brightness = brightness_get, 6116 .get_brightness = brightness_get,
6088 .update_status = brightness_update_status, 6117 .update_status = brightness_update_status,
@@ -6111,8 +6140,8 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6111 6140
6112 /* Models with Intel Extreme Graphics 2 */ 6141 /* Models with Intel Extreme Graphics 2 */
6113 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), 6142 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
6114 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), 6143 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6115 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), 6144 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6116 6145
6117 /* Models with Intel GMA900 */ 6146 /* Models with Intel GMA900 */
6118 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ 6147 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */
@@ -6237,6 +6266,12 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6237 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; 6266 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6238 backlight_update_status(ibm_backlight_device); 6267 backlight_update_status(ibm_backlight_device);
6239 6268
6269 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
6270 "brightness: registering brightness hotkeys "
6271 "as change notification\n");
6272 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
6273 | TP_ACPI_HKEY_BRGHTUP_MASK
6274 | TP_ACPI_HKEY_BRGHTDWN_MASK);;
6240 return 0; 6275 return 0;
6241} 6276}
6242 6277
@@ -6261,23 +6296,22 @@ static void brightness_exit(void)
6261 tpacpi_brightness_checkpoint_nvram(); 6296 tpacpi_brightness_checkpoint_nvram();
6262} 6297}
6263 6298
6264static int brightness_read(char *p) 6299static int brightness_read(struct seq_file *m)
6265{ 6300{
6266 int len = 0;
6267 int level; 6301 int level;
6268 6302
6269 level = brightness_get(NULL); 6303 level = brightness_get(NULL);
6270 if (level < 0) { 6304 if (level < 0) {
6271 len += sprintf(p + len, "level:\t\tunreadable\n"); 6305 seq_printf(m, "level:\t\tunreadable\n");
6272 } else { 6306 } else {
6273 len += sprintf(p + len, "level:\t\t%d\n", level); 6307 seq_printf(m, "level:\t\t%d\n", level);
6274 len += sprintf(p + len, "commands:\tup, down\n"); 6308 seq_printf(m, "commands:\tup, down\n");
6275 len += sprintf(p + len, "commands:\tlevel <level>" 6309 seq_printf(m, "commands:\tlevel <level>"
6276 " (<level> is 0-%d)\n", 6310 " (<level> is 0-%d)\n",
6277 (tp_features.bright_16levels) ? 15 : 7); 6311 (tp_features.bright_16levels) ? 15 : 7);
6278 } 6312 }
6279 6313
6280 return len; 6314 return 0;
6281} 6315}
6282 6316
6283static int brightness_write(char *buf) 6317static int brightness_write(char *buf)
@@ -6313,7 +6347,10 @@ static int brightness_write(char *buf)
6313 * Doing it this way makes the syscall restartable in case of EINTR 6347 * Doing it this way makes the syscall restartable in case of EINTR
6314 */ 6348 */
6315 rc = brightness_set(level); 6349 rc = brightness_set(level);
6316 return (rc == -EINTR)? ERESTARTSYS : rc; 6350 if (!rc && ibm_backlight_device)
6351 backlight_force_update(ibm_backlight_device,
6352 BACKLIGHT_UPDATE_SYSFS);
6353 return (rc == -EINTR)? -ERESTARTSYS : rc;
6317} 6354}
6318 6355
6319static struct ibm_struct brightness_driver_data = { 6356static struct ibm_struct brightness_driver_data = {
@@ -6329,99 +6366,654 @@ static struct ibm_struct brightness_driver_data = {
6329 * Volume subdriver 6366 * Volume subdriver
6330 */ 6367 */
6331 6368
6332static int volume_offset = 0x30; 6369/*
6370 * IBM ThinkPads have a simple volume controller with MUTE gating.
6371 * Very early Lenovo ThinkPads follow the IBM ThinkPad spec.
6372 *
6373 * Since the *61 series (and probably also the later *60 series), Lenovo
6374 * ThinkPads only implement the MUTE gate.
6375 *
6376 * EC register 0x30
6377 * Bit 6: MUTE (1 mutes sound)
6378 * Bit 3-0: Volume
6379 * Other bits should be zero as far as we know.
6380 *
6381 * This is also stored in CMOS NVRAM, byte 0x60, bit 6 (MUTE), and
6382 * bits 3-0 (volume). Other bits in NVRAM may have other functions,
6383 * such as bit 7 which is used to detect repeated presses of MUTE,
6384 * and we leave them unchanged.
6385 */
6386
6387#define TPACPI_ALSA_DRVNAME "ThinkPad EC"
6388#define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
6389#define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME
6390
6391static int alsa_index = SNDRV_DEFAULT_IDX1;
6392static char *alsa_id = "ThinkPadEC";
6393static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
6394
6395struct tpacpi_alsa_data {
6396 struct snd_card *card;
6397 struct snd_ctl_elem_id *ctl_mute_id;
6398 struct snd_ctl_elem_id *ctl_vol_id;
6399};
6400
6401static struct snd_card *alsa_card;
6402
6403enum {
6404 TP_EC_AUDIO = 0x30,
6405
6406 /* TP_EC_AUDIO bits */
6407 TP_EC_AUDIO_MUTESW = 6,
6408
6409 /* TP_EC_AUDIO bitmasks */
6410 TP_EC_AUDIO_LVL_MSK = 0x0F,
6411 TP_EC_AUDIO_MUTESW_MSK = (1 << TP_EC_AUDIO_MUTESW),
6412
6413 /* Maximum volume */
6414 TP_EC_VOLUME_MAX = 14,
6415};
6416
6417enum tpacpi_volume_access_mode {
6418 TPACPI_VOL_MODE_AUTO = 0, /* Not implemented yet */
6419 TPACPI_VOL_MODE_EC, /* Pure EC control */
6420 TPACPI_VOL_MODE_UCMS_STEP, /* UCMS step-based control: N/A */
6421 TPACPI_VOL_MODE_ECNVRAM, /* EC control w/ NVRAM store */
6422 TPACPI_VOL_MODE_MAX
6423};
6424
6425enum tpacpi_volume_capabilities {
6426 TPACPI_VOL_CAP_AUTO = 0, /* Use white/blacklist */
6427 TPACPI_VOL_CAP_VOLMUTE, /* Output vol and mute */
6428 TPACPI_VOL_CAP_MUTEONLY, /* Output mute only */
6429 TPACPI_VOL_CAP_MAX
6430};
6431
6432static enum tpacpi_volume_access_mode volume_mode =
6433 TPACPI_VOL_MODE_MAX;
6333 6434
6334static int volume_read(char *p) 6435static enum tpacpi_volume_capabilities volume_capabilities;
6436static int volume_control_allowed;
6437
6438/*
6439 * Used to syncronize writers to TP_EC_AUDIO and
6440 * TP_NVRAM_ADDR_MIXER, as we need to do read-modify-write
6441 */
6442static struct mutex volume_mutex;
6443
6444static void tpacpi_volume_checkpoint_nvram(void)
6335{ 6445{
6336 int len = 0; 6446 u8 lec = 0;
6337 u8 level; 6447 u8 b_nvram;
6448 u8 ec_mask;
6449
6450 if (volume_mode != TPACPI_VOL_MODE_ECNVRAM)
6451 return;
6452 if (!volume_control_allowed)
6453 return;
6454
6455 vdbg_printk(TPACPI_DBG_MIXER,
6456 "trying to checkpoint mixer state to NVRAM...\n");
6457
6458 if (tp_features.mixer_no_level_control)
6459 ec_mask = TP_EC_AUDIO_MUTESW_MSK;
6460 else
6461 ec_mask = TP_EC_AUDIO_MUTESW_MSK | TP_EC_AUDIO_LVL_MSK;
6338 6462
6339 if (!acpi_ec_read(volume_offset, &level)) { 6463 if (mutex_lock_killable(&volume_mutex) < 0)
6340 len += sprintf(p + len, "level:\t\tunreadable\n"); 6464 return;
6465
6466 if (unlikely(!acpi_ec_read(TP_EC_AUDIO, &lec)))
6467 goto unlock;
6468 lec &= ec_mask;
6469 b_nvram = nvram_read_byte(TP_NVRAM_ADDR_MIXER);
6470
6471 if (lec != (b_nvram & ec_mask)) {
6472 /* NVRAM needs update */
6473 b_nvram &= ~ec_mask;
6474 b_nvram |= lec;
6475 nvram_write_byte(b_nvram, TP_NVRAM_ADDR_MIXER);
6476 dbg_printk(TPACPI_DBG_MIXER,
6477 "updated NVRAM mixer status to 0x%02x (0x%02x)\n",
6478 (unsigned int) lec, (unsigned int) b_nvram);
6341 } else { 6479 } else {
6342 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf); 6480 vdbg_printk(TPACPI_DBG_MIXER,
6343 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6)); 6481 "NVRAM mixer status already is 0x%02x (0x%02x)\n",
6344 len += sprintf(p + len, "commands:\tup, down, mute\n"); 6482 (unsigned int) lec, (unsigned int) b_nvram);
6345 len += sprintf(p + len, "commands:\tlevel <level>"
6346 " (<level> is 0-15)\n");
6347 } 6483 }
6348 6484
6349 return len; 6485unlock:
6486 mutex_unlock(&volume_mutex);
6350} 6487}
6351 6488
6352static int volume_write(char *buf) 6489static int volume_get_status_ec(u8 *status)
6353{ 6490{
6354 int cmos_cmd, inc, i; 6491 u8 s;
6355 u8 level, mute;
6356 int new_level, new_mute;
6357 char *cmd;
6358 6492
6359 while ((cmd = next_cmd(&buf))) { 6493 if (!acpi_ec_read(TP_EC_AUDIO, &s))
6360 if (!acpi_ec_read(volume_offset, &level)) 6494 return -EIO;
6361 return -EIO;
6362 new_mute = mute = level & 0x40;
6363 new_level = level = level & 0xf;
6364 6495
6365 if (strlencmp(cmd, "up") == 0) { 6496 *status = s;
6366 if (mute) 6497
6367 new_mute = 0; 6498 dbg_printk(TPACPI_DBG_MIXER, "status 0x%02x\n", s);
6368 else 6499
6369 new_level = level == 15 ? 15 : level + 1; 6500 return 0;
6370 } else if (strlencmp(cmd, "down") == 0) { 6501}
6371 if (mute)
6372 new_mute = 0;
6373 else
6374 new_level = level == 0 ? 0 : level - 1;
6375 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
6376 new_level >= 0 && new_level <= 15) {
6377 /* new_level set */
6378 } else if (strlencmp(cmd, "mute") == 0) {
6379 new_mute = 0x40;
6380 } else
6381 return -EINVAL;
6382 6502
6383 if (new_level != level) { 6503static int volume_get_status(u8 *status)
6384 /* mute doesn't change */ 6504{
6505 return volume_get_status_ec(status);
6506}
6385 6507
6386 cmos_cmd = (new_level > level) ? 6508static int volume_set_status_ec(const u8 status)
6387 TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN; 6509{
6388 inc = new_level > level ? 1 : -1; 6510 if (!acpi_ec_write(TP_EC_AUDIO, status))
6511 return -EIO;
6389 6512
6390 if (mute && (issue_thinkpad_cmos_command(cmos_cmd) || 6513 dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status);
6391 !acpi_ec_write(volume_offset, level)))
6392 return -EIO;
6393 6514
6394 for (i = level; i != new_level; i += inc) 6515 return 0;
6395 if (issue_thinkpad_cmos_command(cmos_cmd) || 6516}
6396 !acpi_ec_write(volume_offset, i + inc))
6397 return -EIO;
6398 6517
6399 if (mute && 6518static int volume_set_status(const u8 status)
6400 (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) || 6519{
6401 !acpi_ec_write(volume_offset, new_level + mute))) { 6520 return volume_set_status_ec(status);
6402 return -EIO; 6521}
6403 } 6522
6523static int volume_set_mute_ec(const bool mute)
6524{
6525 int rc;
6526 u8 s, n;
6527
6528 if (mutex_lock_killable(&volume_mutex) < 0)
6529 return -EINTR;
6530
6531 rc = volume_get_status_ec(&s);
6532 if (rc)
6533 goto unlock;
6534
6535 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
6536 s & ~TP_EC_AUDIO_MUTESW_MSK;
6537
6538 if (n != s)
6539 rc = volume_set_status_ec(n);
6540
6541unlock:
6542 mutex_unlock(&volume_mutex);
6543 return rc;
6544}
6545
6546static int volume_set_mute(const bool mute)
6547{
6548 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
6549 (mute) ? "" : "un");
6550 return volume_set_mute_ec(mute);
6551}
6552
6553static int volume_set_volume_ec(const u8 vol)
6554{
6555 int rc;
6556 u8 s, n;
6557
6558 if (vol > TP_EC_VOLUME_MAX)
6559 return -EINVAL;
6560
6561 if (mutex_lock_killable(&volume_mutex) < 0)
6562 return -EINTR;
6563
6564 rc = volume_get_status_ec(&s);
6565 if (rc)
6566 goto unlock;
6567
6568 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
6569
6570 if (n != s)
6571 rc = volume_set_status_ec(n);
6572
6573unlock:
6574 mutex_unlock(&volume_mutex);
6575 return rc;
6576}
6577
6578static int volume_set_volume(const u8 vol)
6579{
6580 dbg_printk(TPACPI_DBG_MIXER,
6581 "trying to set volume level to %hu\n", vol);
6582 return volume_set_volume_ec(vol);
6583}
6584
6585static void volume_alsa_notify_change(void)
6586{
6587 struct tpacpi_alsa_data *d;
6588
6589 if (alsa_card && alsa_card->private_data) {
6590 d = alsa_card->private_data;
6591 if (d->ctl_mute_id)
6592 snd_ctl_notify(alsa_card,
6593 SNDRV_CTL_EVENT_MASK_VALUE,
6594 d->ctl_mute_id);
6595 if (d->ctl_vol_id)
6596 snd_ctl_notify(alsa_card,
6597 SNDRV_CTL_EVENT_MASK_VALUE,
6598 d->ctl_vol_id);
6599 }
6600}
6601
6602static int volume_alsa_vol_info(struct snd_kcontrol *kcontrol,
6603 struct snd_ctl_elem_info *uinfo)
6604{
6605 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
6606 uinfo->count = 1;
6607 uinfo->value.integer.min = 0;
6608 uinfo->value.integer.max = TP_EC_VOLUME_MAX;
6609 return 0;
6610}
6611
6612static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
6613 struct snd_ctl_elem_value *ucontrol)
6614{
6615 u8 s;
6616 int rc;
6617
6618 rc = volume_get_status(&s);
6619 if (rc < 0)
6620 return rc;
6621
6622 ucontrol->value.integer.value[0] = s & TP_EC_AUDIO_LVL_MSK;
6623 return 0;
6624}
6625
6626static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
6627 struct snd_ctl_elem_value *ucontrol)
6628{
6629 return volume_set_volume(ucontrol->value.integer.value[0]);
6630}
6631
6632#define volume_alsa_mute_info snd_ctl_boolean_mono_info
6633
6634static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
6635 struct snd_ctl_elem_value *ucontrol)
6636{
6637 u8 s;
6638 int rc;
6639
6640 rc = volume_get_status(&s);
6641 if (rc < 0)
6642 return rc;
6643
6644 ucontrol->value.integer.value[0] =
6645 (s & TP_EC_AUDIO_MUTESW_MSK) ? 0 : 1;
6646 return 0;
6647}
6648
6649static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
6650 struct snd_ctl_elem_value *ucontrol)
6651{
6652 return volume_set_mute(!ucontrol->value.integer.value[0]);
6653}
6654
6655static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
6656 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6657 .name = "Console Playback Volume",
6658 .index = 0,
6659 .access = SNDRV_CTL_ELEM_ACCESS_READ,
6660 .info = volume_alsa_vol_info,
6661 .get = volume_alsa_vol_get,
6662};
6663
6664static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
6665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6666 .name = "Console Playback Switch",
6667 .index = 0,
6668 .access = SNDRV_CTL_ELEM_ACCESS_READ,
6669 .info = volume_alsa_mute_info,
6670 .get = volume_alsa_mute_get,
6671};
6672
6673static void volume_suspend(pm_message_t state)
6674{
6675 tpacpi_volume_checkpoint_nvram();
6676}
6677
6678static void volume_resume(void)
6679{
6680 volume_alsa_notify_change();
6681}
6682
6683static void volume_shutdown(void)
6684{
6685 tpacpi_volume_checkpoint_nvram();
6686}
6687
6688static void volume_exit(void)
6689{
6690 if (alsa_card) {
6691 snd_card_free(alsa_card);
6692 alsa_card = NULL;
6693 }
6694
6695 tpacpi_volume_checkpoint_nvram();
6696}
6697
6698static int __init volume_create_alsa_mixer(void)
6699{
6700 struct snd_card *card;
6701 struct tpacpi_alsa_data *data;
6702 struct snd_kcontrol *ctl_vol;
6703 struct snd_kcontrol *ctl_mute;
6704 int rc;
6705
6706 rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
6707 sizeof(struct tpacpi_alsa_data), &card);
6708 if (rc < 0)
6709 return rc;
6710 if (!card)
6711 return -ENOMEM;
6712
6713 BUG_ON(!card->private_data);
6714 data = card->private_data;
6715 data->card = card;
6716
6717 strlcpy(card->driver, TPACPI_ALSA_DRVNAME,
6718 sizeof(card->driver));
6719 strlcpy(card->shortname, TPACPI_ALSA_SHRTNAME,
6720 sizeof(card->shortname));
6721 snprintf(card->mixername, sizeof(card->mixername), "ThinkPad EC %s",
6722 (thinkpad_id.ec_version_str) ?
6723 thinkpad_id.ec_version_str : "(unknown)");
6724 snprintf(card->longname, sizeof(card->longname),
6725 "%s at EC reg 0x%02x, fw %s", card->shortname, TP_EC_AUDIO,
6726 (thinkpad_id.ec_version_str) ?
6727 thinkpad_id.ec_version_str : "unknown");
6728
6729 if (volume_control_allowed) {
6730 volume_alsa_control_vol.put = volume_alsa_vol_put;
6731 volume_alsa_control_vol.access =
6732 SNDRV_CTL_ELEM_ACCESS_READWRITE;
6733
6734 volume_alsa_control_mute.put = volume_alsa_mute_put;
6735 volume_alsa_control_mute.access =
6736 SNDRV_CTL_ELEM_ACCESS_READWRITE;
6737 }
6738
6739 if (!tp_features.mixer_no_level_control) {
6740 ctl_vol = snd_ctl_new1(&volume_alsa_control_vol, NULL);
6741 rc = snd_ctl_add(card, ctl_vol);
6742 if (rc < 0) {
6743 printk(TPACPI_ERR
6744 "Failed to create ALSA volume control\n");
6745 goto err_out;
6404 } 6746 }
6747 data->ctl_vol_id = &ctl_vol->id;
6748 }
6405 6749
6406 if (new_mute != mute) { 6750 ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL);
6407 /* level doesn't change */ 6751 rc = snd_ctl_add(card, ctl_mute);
6752 if (rc < 0) {
6753 printk(TPACPI_ERR "Failed to create ALSA mute control\n");
6754 goto err_out;
6755 }
6756 data->ctl_mute_id = &ctl_mute->id;
6408 6757
6409 cmos_cmd = (new_mute) ? 6758 snd_card_set_dev(card, &tpacpi_pdev->dev);
6410 TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP; 6759 rc = snd_card_register(card);
6411 6760
6412 if (issue_thinkpad_cmos_command(cmos_cmd) || 6761err_out:
6413 !acpi_ec_write(volume_offset, level + new_mute)) 6762 if (rc < 0) {
6414 return -EIO; 6763 snd_card_free(card);
6764 card = NULL;
6765 }
6766
6767 alsa_card = card;
6768 return rc;
6769}
6770
6771#define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */
6772#define TPACPI_VOL_Q_LEVEL 0x0002 /* Volume control available */
6773
6774static const struct tpacpi_quirk volume_quirk_table[] __initconst = {
6775 /* Whitelist volume level on all IBM by default */
6776 { .vendor = PCI_VENDOR_ID_IBM,
6777 .bios = TPACPI_MATCH_ANY,
6778 .ec = TPACPI_MATCH_ANY,
6779 .quirks = TPACPI_VOL_Q_LEVEL },
6780
6781 /* Lenovo models with volume control (needs confirmation) */
6782 TPACPI_QEC_LNV('7', 'C', TPACPI_VOL_Q_LEVEL), /* R60/i */
6783 TPACPI_QEC_LNV('7', 'E', TPACPI_VOL_Q_LEVEL), /* R60e/i */
6784 TPACPI_QEC_LNV('7', '9', TPACPI_VOL_Q_LEVEL), /* T60/p */
6785 TPACPI_QEC_LNV('7', 'B', TPACPI_VOL_Q_LEVEL), /* X60/s */
6786 TPACPI_QEC_LNV('7', 'J', TPACPI_VOL_Q_LEVEL), /* X60t */
6787 TPACPI_QEC_LNV('7', '7', TPACPI_VOL_Q_LEVEL), /* Z60 */
6788 TPACPI_QEC_LNV('7', 'F', TPACPI_VOL_Q_LEVEL), /* Z61 */
6789
6790 /* Whitelist mute-only on all Lenovo by default */
6791 { .vendor = PCI_VENDOR_ID_LENOVO,
6792 .bios = TPACPI_MATCH_ANY,
6793 .ec = TPACPI_MATCH_ANY,
6794 .quirks = TPACPI_VOL_Q_MUTEONLY }
6795};
6796
6797static int __init volume_init(struct ibm_init_struct *iibm)
6798{
6799 unsigned long quirks;
6800 int rc;
6801
6802 vdbg_printk(TPACPI_DBG_INIT, "initializing volume subdriver\n");
6803
6804 mutex_init(&volume_mutex);
6805
6806 /*
6807 * Check for module parameter bogosity, note that we
6808 * init volume_mode to TPACPI_VOL_MODE_MAX in order to be
6809 * able to detect "unspecified"
6810 */
6811 if (volume_mode > TPACPI_VOL_MODE_MAX)
6812 return -EINVAL;
6813
6814 if (volume_mode == TPACPI_VOL_MODE_UCMS_STEP) {
6815 printk(TPACPI_ERR
6816 "UCMS step volume mode not implemented, "
6817 "please contact %s\n", TPACPI_MAIL);
6818 return 1;
6819 }
6820
6821 if (volume_capabilities >= TPACPI_VOL_CAP_MAX)
6822 return -EINVAL;
6823
6824 /*
6825 * The ALSA mixer is our primary interface.
6826 * When disabled, don't install the subdriver at all
6827 */
6828 if (!alsa_enable) {
6829 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6830 "ALSA mixer disabled by parameter, "
6831 "not loading volume subdriver...\n");
6832 return 1;
6833 }
6834
6835 quirks = tpacpi_check_quirks(volume_quirk_table,
6836 ARRAY_SIZE(volume_quirk_table));
6837
6838 switch (volume_capabilities) {
6839 case TPACPI_VOL_CAP_AUTO:
6840 if (quirks & TPACPI_VOL_Q_MUTEONLY)
6841 tp_features.mixer_no_level_control = 1;
6842 else if (quirks & TPACPI_VOL_Q_LEVEL)
6843 tp_features.mixer_no_level_control = 0;
6844 else
6845 return 1; /* no mixer */
6846 break;
6847 case TPACPI_VOL_CAP_VOLMUTE:
6848 tp_features.mixer_no_level_control = 0;
6849 break;
6850 case TPACPI_VOL_CAP_MUTEONLY:
6851 tp_features.mixer_no_level_control = 1;
6852 break;
6853 default:
6854 return 1;
6855 }
6856
6857 if (volume_capabilities != TPACPI_VOL_CAP_AUTO)
6858 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6859 "using user-supplied volume_capabilities=%d\n",
6860 volume_capabilities);
6861
6862 if (volume_mode == TPACPI_VOL_MODE_AUTO ||
6863 volume_mode == TPACPI_VOL_MODE_MAX) {
6864 volume_mode = TPACPI_VOL_MODE_ECNVRAM;
6865
6866 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6867 "driver auto-selected volume_mode=%d\n",
6868 volume_mode);
6869 } else {
6870 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6871 "using user-supplied volume_mode=%d\n",
6872 volume_mode);
6873 }
6874
6875 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6876 "mute is supported, volume control is %s\n",
6877 str_supported(!tp_features.mixer_no_level_control));
6878
6879 rc = volume_create_alsa_mixer();
6880 if (rc) {
6881 printk(TPACPI_ERR
6882 "Could not create the ALSA mixer interface\n");
6883 return rc;
6884 }
6885
6886 printk(TPACPI_INFO
6887 "Console audio control enabled, mode: %s\n",
6888 (volume_control_allowed) ?
6889 "override (read/write)" :
6890 "monitor (read only)");
6891
6892 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6893 "registering volume hotkeys as change notification\n");
6894 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
6895 | TP_ACPI_HKEY_VOLUP_MASK
6896 | TP_ACPI_HKEY_VOLDWN_MASK
6897 | TP_ACPI_HKEY_MUTE_MASK);
6898
6899 return 0;
6900}
6901
6902static int volume_read(struct seq_file *m)
6903{
6904 u8 status;
6905
6906 if (volume_get_status(&status) < 0) {
6907 seq_printf(m, "level:\t\tunreadable\n");
6908 } else {
6909 if (tp_features.mixer_no_level_control)
6910 seq_printf(m, "level:\t\tunsupported\n");
6911 else
6912 seq_printf(m, "level:\t\t%d\n",
6913 status & TP_EC_AUDIO_LVL_MSK);
6914
6915 seq_printf(m, "mute:\t\t%s\n",
6916 onoff(status, TP_EC_AUDIO_MUTESW));
6917
6918 if (volume_control_allowed) {
6919 seq_printf(m, "commands:\tunmute, mute\n");
6920 if (!tp_features.mixer_no_level_control) {
6921 seq_printf(m,
6922 "commands:\tup, down\n");
6923 seq_printf(m,
6924 "commands:\tlevel <level>"
6925 " (<level> is 0-%d)\n",
6926 TP_EC_VOLUME_MAX);
6927 }
6415 } 6928 }
6416 } 6929 }
6417 6930
6418 return 0; 6931 return 0;
6419} 6932}
6420 6933
6934static int volume_write(char *buf)
6935{
6936 u8 s;
6937 u8 new_level, new_mute;
6938 int l;
6939 char *cmd;
6940 int rc;
6941
6942 /*
6943 * We do allow volume control at driver startup, so that the
6944 * user can set initial state through the volume=... parameter hack.
6945 */
6946 if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT) {
6947 if (unlikely(!tp_warned.volume_ctrl_forbidden)) {
6948 tp_warned.volume_ctrl_forbidden = 1;
6949 printk(TPACPI_NOTICE
6950 "Console audio control in monitor mode, "
6951 "changes are not allowed.\n");
6952 printk(TPACPI_NOTICE
6953 "Use the volume_control=1 module parameter "
6954 "to enable volume control\n");
6955 }
6956 return -EPERM;
6957 }
6958
6959 rc = volume_get_status(&s);
6960 if (rc < 0)
6961 return rc;
6962
6963 new_level = s & TP_EC_AUDIO_LVL_MSK;
6964 new_mute = s & TP_EC_AUDIO_MUTESW_MSK;
6965
6966 while ((cmd = next_cmd(&buf))) {
6967 if (!tp_features.mixer_no_level_control) {
6968 if (strlencmp(cmd, "up") == 0) {
6969 if (new_mute)
6970 new_mute = 0;
6971 else if (new_level < TP_EC_VOLUME_MAX)
6972 new_level++;
6973 continue;
6974 } else if (strlencmp(cmd, "down") == 0) {
6975 if (new_mute)
6976 new_mute = 0;
6977 else if (new_level > 0)
6978 new_level--;
6979 continue;
6980 } else if (sscanf(cmd, "level %u", &l) == 1 &&
6981 l >= 0 && l <= TP_EC_VOLUME_MAX) {
6982 new_level = l;
6983 continue;
6984 }
6985 }
6986 if (strlencmp(cmd, "mute") == 0)
6987 new_mute = TP_EC_AUDIO_MUTESW_MSK;
6988 else if (strlencmp(cmd, "unmute") == 0)
6989 new_mute = 0;
6990 else
6991 return -EINVAL;
6992 }
6993
6994 if (tp_features.mixer_no_level_control) {
6995 tpacpi_disclose_usertask("procfs volume", "%smute\n",
6996 new_mute ? "" : "un");
6997 rc = volume_set_mute(!!new_mute);
6998 } else {
6999 tpacpi_disclose_usertask("procfs volume",
7000 "%smute and set level to %d\n",
7001 new_mute ? "" : "un", new_level);
7002 rc = volume_set_status(new_mute | new_level);
7003 }
7004 volume_alsa_notify_change();
7005
7006 return (rc == -EINTR) ? -ERESTARTSYS : rc;
7007}
7008
6421static struct ibm_struct volume_driver_data = { 7009static struct ibm_struct volume_driver_data = {
6422 .name = "volume", 7010 .name = "volume",
6423 .read = volume_read, 7011 .read = volume_read,
6424 .write = volume_write, 7012 .write = volume_write,
7013 .exit = volume_exit,
7014 .suspend = volume_suspend,
7015 .resume = volume_resume,
7016 .shutdown = volume_shutdown,
6425}; 7017};
6426 7018
6427/************************************************************************* 7019/*************************************************************************
@@ -6533,7 +7125,7 @@ static struct ibm_struct volume_driver_data = {
6533 * The speeds are stored on handles 7125 * The speeds are stored on handles
6534 * (FANA:FAN9), (FANC:FANB), (FANE:FAND). 7126 * (FANA:FAN9), (FANC:FANB), (FANE:FAND).
6535 * 7127 *
6536 * There are three default speed sets, acessible as handles: 7128 * There are three default speed sets, accessible as handles:
6537 * FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H 7129 * FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
6538 * 7130 *
6539 * ACPI DSDT switches which set is in use depending on various 7131 * ACPI DSDT switches which set is in use depending on various
@@ -7498,9 +8090,8 @@ static void fan_resume(void)
7498 } 8090 }
7499} 8091}
7500 8092
7501static int fan_read(char *p) 8093static int fan_read(struct seq_file *m)
7502{ 8094{
7503 int len = 0;
7504 int rc; 8095 int rc;
7505 u8 status; 8096 u8 status;
7506 unsigned int speed = 0; 8097 unsigned int speed = 0;
@@ -7512,7 +8103,7 @@ static int fan_read(char *p)
7512 if (rc < 0) 8103 if (rc < 0)
7513 return rc; 8104 return rc;
7514 8105
7515 len += sprintf(p + len, "status:\t\t%s\n" 8106 seq_printf(m, "status:\t\t%s\n"
7516 "level:\t\t%d\n", 8107 "level:\t\t%d\n",
7517 (status != 0) ? "enabled" : "disabled", status); 8108 (status != 0) ? "enabled" : "disabled", status);
7518 break; 8109 break;
@@ -7523,54 +8114,54 @@ static int fan_read(char *p)
7523 if (rc < 0) 8114 if (rc < 0)
7524 return rc; 8115 return rc;
7525 8116
7526 len += sprintf(p + len, "status:\t\t%s\n", 8117 seq_printf(m, "status:\t\t%s\n",
7527 (status != 0) ? "enabled" : "disabled"); 8118 (status != 0) ? "enabled" : "disabled");
7528 8119
7529 rc = fan_get_speed(&speed); 8120 rc = fan_get_speed(&speed);
7530 if (rc < 0) 8121 if (rc < 0)
7531 return rc; 8122 return rc;
7532 8123
7533 len += sprintf(p + len, "speed:\t\t%d\n", speed); 8124 seq_printf(m, "speed:\t\t%d\n", speed);
7534 8125
7535 if (status & TP_EC_FAN_FULLSPEED) 8126 if (status & TP_EC_FAN_FULLSPEED)
7536 /* Disengaged mode takes precedence */ 8127 /* Disengaged mode takes precedence */
7537 len += sprintf(p + len, "level:\t\tdisengaged\n"); 8128 seq_printf(m, "level:\t\tdisengaged\n");
7538 else if (status & TP_EC_FAN_AUTO) 8129 else if (status & TP_EC_FAN_AUTO)
7539 len += sprintf(p + len, "level:\t\tauto\n"); 8130 seq_printf(m, "level:\t\tauto\n");
7540 else 8131 else
7541 len += sprintf(p + len, "level:\t\t%d\n", status); 8132 seq_printf(m, "level:\t\t%d\n", status);
7542 break; 8133 break;
7543 8134
7544 case TPACPI_FAN_NONE: 8135 case TPACPI_FAN_NONE:
7545 default: 8136 default:
7546 len += sprintf(p + len, "status:\t\tnot supported\n"); 8137 seq_printf(m, "status:\t\tnot supported\n");
7547 } 8138 }
7548 8139
7549 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) { 8140 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
7550 len += sprintf(p + len, "commands:\tlevel <level>"); 8141 seq_printf(m, "commands:\tlevel <level>");
7551 8142
7552 switch (fan_control_access_mode) { 8143 switch (fan_control_access_mode) {
7553 case TPACPI_FAN_WR_ACPI_SFAN: 8144 case TPACPI_FAN_WR_ACPI_SFAN:
7554 len += sprintf(p + len, " (<level> is 0-7)\n"); 8145 seq_printf(m, " (<level> is 0-7)\n");
7555 break; 8146 break;
7556 8147
7557 default: 8148 default:
7558 len += sprintf(p + len, " (<level> is 0-7, " 8149 seq_printf(m, " (<level> is 0-7, "
7559 "auto, disengaged, full-speed)\n"); 8150 "auto, disengaged, full-speed)\n");
7560 break; 8151 break;
7561 } 8152 }
7562 } 8153 }
7563 8154
7564 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE) 8155 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
7565 len += sprintf(p + len, "commands:\tenable, disable\n" 8156 seq_printf(m, "commands:\tenable, disable\n"
7566 "commands:\twatchdog <timeout> (<timeout> " 8157 "commands:\twatchdog <timeout> (<timeout> "
7567 "is 0 (off), 1-120 (seconds))\n"); 8158 "is 0 (off), 1-120 (seconds))\n");
7568 8159
7569 if (fan_control_commands & TPACPI_FAN_CMD_SPEED) 8160 if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
7570 len += sprintf(p + len, "commands:\tspeed <speed>" 8161 seq_printf(m, "commands:\tspeed <speed>"
7571 " (<speed> is 0-65535)\n"); 8162 " (<speed> is 0-65535)\n");
7572 8163
7573 return len; 8164 return 0;
7574} 8165}
7575 8166
7576static int fan_write_cmd_level(const char *cmd, int *rc) 8167static int fan_write_cmd_level(const char *cmd, int *rc)
@@ -7712,10 +8303,23 @@ static struct ibm_struct fan_driver_data = {
7712 */ 8303 */
7713static void tpacpi_driver_event(const unsigned int hkey_event) 8304static void tpacpi_driver_event(const unsigned int hkey_event)
7714{ 8305{
8306 if (ibm_backlight_device) {
8307 switch (hkey_event) {
8308 case TP_HKEY_EV_BRGHT_UP:
8309 case TP_HKEY_EV_BRGHT_DOWN:
8310 tpacpi_brightness_notify_change();
8311 }
8312 }
8313 if (alsa_card) {
8314 switch (hkey_event) {
8315 case TP_HKEY_EV_VOL_UP:
8316 case TP_HKEY_EV_VOL_DOWN:
8317 case TP_HKEY_EV_VOL_MUTE:
8318 volume_alsa_notify_change();
8319 }
8320 }
7715} 8321}
7716 8322
7717
7718
7719static void hotkey_driver_event(const unsigned int scancode) 8323static void hotkey_driver_event(const unsigned int scancode)
7720{ 8324{
7721 tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode); 8325 tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode);
@@ -7844,19 +8448,19 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
7844 "%s installed\n", ibm->name); 8448 "%s installed\n", ibm->name);
7845 8449
7846 if (ibm->read) { 8450 if (ibm->read) {
7847 entry = create_proc_entry(ibm->name, 8451 mode_t mode;
7848 S_IFREG | S_IRUGO | S_IWUSR, 8452
7849 proc_dir); 8453 mode = S_IRUGO;
8454 if (ibm->write)
8455 mode |= S_IWUSR;
8456 entry = proc_create_data(ibm->name, mode, proc_dir,
8457 &dispatch_proc_fops, ibm);
7850 if (!entry) { 8458 if (!entry) {
7851 printk(TPACPI_ERR "unable to create proc entry %s\n", 8459 printk(TPACPI_ERR "unable to create proc entry %s\n",
7852 ibm->name); 8460 ibm->name);
7853 ret = -ENODEV; 8461 ret = -ENODEV;
7854 goto err_out; 8462 goto err_out;
7855 } 8463 }
7856 entry->data = ibm;
7857 entry->read_proc = &dispatch_procfs_read;
7858 if (ibm->write)
7859 entry->write_proc = &dispatch_procfs_write;
7860 ibm->flags.proc_created = 1; 8464 ibm->flags.proc_created = 1;
7861 } 8465 }
7862 8466
@@ -8068,6 +8672,7 @@ static struct ibm_init_struct ibms_init[] __initdata = {
8068 .data = &brightness_driver_data, 8672 .data = &brightness_driver_data,
8069 }, 8673 },
8070 { 8674 {
8675 .init = volume_init,
8071 .data = &volume_driver_data, 8676 .data = &volume_driver_data,
8072 }, 8677 },
8073 { 8678 {
@@ -8103,36 +8708,59 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp)
8103 return -EINVAL; 8708 return -EINVAL;
8104} 8709}
8105 8710
8106module_param(experimental, int, 0); 8711module_param(experimental, int, 0444);
8107MODULE_PARM_DESC(experimental, 8712MODULE_PARM_DESC(experimental,
8108 "Enables experimental features when non-zero"); 8713 "Enables experimental features when non-zero");
8109 8714
8110module_param_named(debug, dbg_level, uint, 0); 8715module_param_named(debug, dbg_level, uint, 0);
8111MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); 8716MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
8112 8717
8113module_param(force_load, bool, 0); 8718module_param(force_load, bool, 0444);
8114MODULE_PARM_DESC(force_load, 8719MODULE_PARM_DESC(force_load,
8115 "Attempts to load the driver even on a " 8720 "Attempts to load the driver even on a "
8116 "mis-identified ThinkPad when true"); 8721 "mis-identified ThinkPad when true");
8117 8722
8118module_param_named(fan_control, fan_control_allowed, bool, 0); 8723module_param_named(fan_control, fan_control_allowed, bool, 0444);
8119MODULE_PARM_DESC(fan_control, 8724MODULE_PARM_DESC(fan_control,
8120 "Enables setting fan parameters features when true"); 8725 "Enables setting fan parameters features when true");
8121 8726
8122module_param_named(brightness_mode, brightness_mode, uint, 0); 8727module_param_named(brightness_mode, brightness_mode, uint, 0444);
8123MODULE_PARM_DESC(brightness_mode, 8728MODULE_PARM_DESC(brightness_mode,
8124 "Selects brightness control strategy: " 8729 "Selects brightness control strategy: "
8125 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM"); 8730 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
8126 8731
8127module_param(brightness_enable, uint, 0); 8732module_param(brightness_enable, uint, 0444);
8128MODULE_PARM_DESC(brightness_enable, 8733MODULE_PARM_DESC(brightness_enable,
8129 "Enables backlight control when 1, disables when 0"); 8734 "Enables backlight control when 1, disables when 0");
8130 8735
8131module_param(hotkey_report_mode, uint, 0); 8736module_param(hotkey_report_mode, uint, 0444);
8132MODULE_PARM_DESC(hotkey_report_mode, 8737MODULE_PARM_DESC(hotkey_report_mode,
8133 "used for backwards compatibility with userspace, " 8738 "used for backwards compatibility with userspace, "
8134 "see documentation"); 8739 "see documentation");
8135 8740
8741module_param_named(volume_mode, volume_mode, uint, 0444);
8742MODULE_PARM_DESC(volume_mode,
8743 "Selects volume control strategy: "
8744 "0=auto, 1=EC, 2=N/A, 3=EC+NVRAM");
8745
8746module_param_named(volume_capabilities, volume_capabilities, uint, 0444);
8747MODULE_PARM_DESC(volume_capabilities,
8748 "Selects the mixer capabilites: "
8749 "0=auto, 1=volume and mute, 2=mute only");
8750
8751module_param_named(volume_control, volume_control_allowed, bool, 0444);
8752MODULE_PARM_DESC(volume_control,
8753 "Enables software override for the console audio "
8754 "control when true");
8755
8756/* ALSA module API parameters */
8757module_param_named(index, alsa_index, int, 0444);
8758MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer");
8759module_param_named(id, alsa_id, charp, 0444);
8760MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer");
8761module_param_named(enable, alsa_enable, bool, 0444);
8762MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer");
8763
8136#define TPACPI_PARAM(feature) \ 8764#define TPACPI_PARAM(feature) \
8137 module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ 8765 module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
8138 MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \ 8766 MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \
@@ -8151,25 +8779,25 @@ TPACPI_PARAM(volume);
8151TPACPI_PARAM(fan); 8779TPACPI_PARAM(fan);
8152 8780
8153#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 8781#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
8154module_param(dbg_wlswemul, uint, 0); 8782module_param(dbg_wlswemul, uint, 0444);
8155MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation"); 8783MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
8156module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0); 8784module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
8157MODULE_PARM_DESC(wlsw_state, 8785MODULE_PARM_DESC(wlsw_state,
8158 "Initial state of the emulated WLSW switch"); 8786 "Initial state of the emulated WLSW switch");
8159 8787
8160module_param(dbg_bluetoothemul, uint, 0); 8788module_param(dbg_bluetoothemul, uint, 0444);
8161MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation"); 8789MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
8162module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0); 8790module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
8163MODULE_PARM_DESC(bluetooth_state, 8791MODULE_PARM_DESC(bluetooth_state,
8164 "Initial state of the emulated bluetooth switch"); 8792 "Initial state of the emulated bluetooth switch");
8165 8793
8166module_param(dbg_wwanemul, uint, 0); 8794module_param(dbg_wwanemul, uint, 0444);
8167MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation"); 8795MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
8168module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0); 8796module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
8169MODULE_PARM_DESC(wwan_state, 8797MODULE_PARM_DESC(wwan_state,
8170 "Initial state of the emulated WWAN switch"); 8798 "Initial state of the emulated WWAN switch");
8171 8799
8172module_param(dbg_uwbemul, uint, 0); 8800module_param(dbg_uwbemul, uint, 0444);
8173MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation"); 8801MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
8174module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0); 8802module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
8175MODULE_PARM_DESC(uwb_state, 8803MODULE_PARM_DESC(uwb_state,
@@ -8362,6 +8990,7 @@ static int __init thinkpad_acpi_module_init(void)
8362 PCI_VENDOR_ID_IBM; 8990 PCI_VENDOR_ID_IBM;
8363 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; 8991 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
8364 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 8992 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
8993 tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
8365 } 8994 }
8366 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 8995 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
8367 ret = ibm_init(&ibms_init[i]); 8996 ret = ibm_init(&ibms_init[i]);