aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-02-26 20:20:18 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-02-26 20:20:18 -0500
commit98723153dc32106e5be701da15551853c9f785a9 (patch)
treea04631cbeb50703474ac4f5f20310f7ef53b2b38
parent4cbd55188fe01f22783815cbb6d4f55a0ebf5969 (diff)
parent6335e4d56681f6f08f24f4b812a72d402793d393 (diff)
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86: toshiba_acpi: Add full hotkey support hp-wmi: Add support for tablet rotation key dell-laptop: Add another Dell laptop to the DMI whitelist classmate-laptop: use a single MODULE_DEVICE_TABLE to get correct aliases dell-laptop: Pay attention to which devices the hardware switch controls dell-laptop: Use buffer with 32-bit physical address dell-laptop: Blacklist machines not supporting dell-laptop dell-laptop: Block software state changes when rfkill hard blocked dell-laptop: Fix small memory leak dell-laptop: Fix platform device unregistration dell-laptop: Update rfkill state on kill switch compal-laptop: Replace sysfs support with rfkill support compal-laptop: Add support for known Compal made Dell laptops MAINTAINERS: update drivers/platform/x86 information
-rw-r--r--MAINTAINERS29
-rw-r--r--drivers/platform/x86/Kconfig1
-rw-r--r--drivers/platform/x86/classmate-laptop.c31
-rw-r--r--drivers/platform/x86/compal-laptop.c247
-rw-r--r--drivers/platform/x86/dell-laptop.c256
-rw-r--r--drivers/platform/x86/hp-wmi.c1
-rw-r--r--drivers/platform/x86/toshiba_acpi.c206
7 files changed, 575 insertions, 196 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index a0491af7b243..2653b44f90da 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -221,6 +221,7 @@ F: drivers/net/acenic*
221 221
222ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER 222ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER
223M: Peter Feuerer <peter@piie.net> 223M: Peter Feuerer <peter@piie.net>
224L: platform-driver-x86@vger.kernel.org
224W: http://piie.net/?section=acerhdf 225W: http://piie.net/?section=acerhdf
225S: Maintained 226S: Maintained
226F: drivers/platform/x86/acerhdf.c 227F: drivers/platform/x86/acerhdf.c
@@ -228,6 +229,7 @@ F: drivers/platform/x86/acerhdf.c
228ACER WMI LAPTOP EXTRAS 229ACER WMI LAPTOP EXTRAS
229M: Carlos Corbacho <carlos@strangeworlds.co.uk> 230M: Carlos Corbacho <carlos@strangeworlds.co.uk>
230L: aceracpi@googlegroups.com (subscribers-only) 231L: aceracpi@googlegroups.com (subscribers-only)
232L: platform-driver-x86@vger.kernel.org
231W: http://code.google.com/p/aceracpi 233W: http://code.google.com/p/aceracpi
232S: Maintained 234S: Maintained
233F: drivers/platform/x86/acer-wmi.c 235F: drivers/platform/x86/acer-wmi.c
@@ -288,7 +290,7 @@ F: drivers/acpi/video.c
288 290
289ACPI WMI DRIVER 291ACPI WMI DRIVER
290M: Carlos Corbacho <carlos@strangeworlds.co.uk> 292M: Carlos Corbacho <carlos@strangeworlds.co.uk>
291L: linux-acpi@vger.kernel.org 293L: platform-driver-x86@vger.kernel.org
292W: http://www.lesswatts.org/projects/acpi/ 294W: http://www.lesswatts.org/projects/acpi/
293S: Maintained 295S: Maintained
294F: drivers/platform/x86/wmi.c 296F: drivers/platform/x86/wmi.c
@@ -968,6 +970,7 @@ ASUS ACPI EXTRAS DRIVER
968M: Corentin Chary <corentincj@iksaif.net> 970M: Corentin Chary <corentincj@iksaif.net>
969M: Karol Kozimor <sziwan@users.sourceforge.net> 971M: Karol Kozimor <sziwan@users.sourceforge.net>
970L: acpi4asus-user@lists.sourceforge.net 972L: acpi4asus-user@lists.sourceforge.net
973L: platform-driver-x86@vger.kernel.org
971W: http://acpi4asus.sf.net 974W: http://acpi4asus.sf.net
972S: Maintained 975S: Maintained
973F: drivers/platform/x86/asus_acpi.c 976F: drivers/platform/x86/asus_acpi.c
@@ -981,6 +984,7 @@ F: drivers/hwmon/asb100.c
981ASUS LAPTOP EXTRAS DRIVER 984ASUS LAPTOP EXTRAS DRIVER
982M: Corentin Chary <corentincj@iksaif.net> 985M: Corentin Chary <corentincj@iksaif.net>
983L: acpi4asus-user@lists.sourceforge.net 986L: acpi4asus-user@lists.sourceforge.net
987L: platform-driver-x86@vger.kernel.org
984W: http://acpi4asus.sf.net 988W: http://acpi4asus.sf.net
985S: Maintained 989S: Maintained
986F: drivers/platform/x86/asus-laptop.c 990F: drivers/platform/x86/asus-laptop.c
@@ -1473,6 +1477,7 @@ F: drivers/scsi/fnic/
1473CMPC ACPI DRIVER 1477CMPC ACPI DRIVER
1474M: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> 1478M: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
1475M: Daniel Oliveira Nascimento <don@syst.com.br> 1479M: Daniel Oliveira Nascimento <don@syst.com.br>
1480L: platform-driver-x86@vger.kernel.org
1476S: Supported 1481S: Supported
1477F: drivers/platform/x86/classmate-laptop.c 1482F: drivers/platform/x86/classmate-laptop.c
1478 1483
@@ -1516,6 +1521,7 @@ F: drivers/pci/hotplug/cpcihp_generic.c
1516 1521
1517COMPAL LAPTOP SUPPORT 1522COMPAL LAPTOP SUPPORT
1518M: Cezary Jackiewicz <cezary.jackiewicz@gmail.com> 1523M: Cezary Jackiewicz <cezary.jackiewicz@gmail.com>
1524L: platform-driver-x86@vger.kernel.org
1519S: Maintained 1525S: Maintained
1520F: drivers/platform/x86/compal-laptop.c 1526F: drivers/platform/x86/compal-laptop.c
1521 1527
@@ -1746,6 +1752,7 @@ F: drivers/net/defxx.*
1746 1752
1747DELL LAPTOP DRIVER 1753DELL LAPTOP DRIVER
1748M: Matthew Garrett <mjg59@srcf.ucam.org> 1754M: Matthew Garrett <mjg59@srcf.ucam.org>
1755L: platform-driver-x86@vger.kernel.org
1749S: Maintained 1756S: Maintained
1750F: drivers/platform/x86/dell-laptop.c 1757F: drivers/platform/x86/dell-laptop.c
1751 1758
@@ -2028,6 +2035,7 @@ F: drivers/edac/r82600_edac.c
2028EEEPC LAPTOP EXTRAS DRIVER 2035EEEPC LAPTOP EXTRAS DRIVER
2029M: Corentin Chary <corentincj@iksaif.net> 2036M: Corentin Chary <corentincj@iksaif.net>
2030L: acpi4asus-user@lists.sourceforge.net 2037L: acpi4asus-user@lists.sourceforge.net
2038L: platform-driver-x86@vger.kernel.org
2031W: http://acpi4asus.sf.net 2039W: http://acpi4asus.sf.net
2032S: Maintained 2040S: Maintained
2033F: drivers/platform/x86/eeepc-laptop.c 2041F: drivers/platform/x86/eeepc-laptop.c
@@ -2306,7 +2314,7 @@ F: arch/frv/
2306 2314
2307FUJITSU LAPTOP EXTRAS 2315FUJITSU LAPTOP EXTRAS
2308M: Jonathan Woithe <jwoithe@physics.adelaide.edu.au> 2316M: Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
2309L: linux-acpi@vger.kernel.org 2317L: platform-driver-x86@vger.kernel.org
2310S: Maintained 2318S: Maintained
2311F: drivers/platform/x86/fujitsu-laptop.c 2319F: drivers/platform/x86/fujitsu-laptop.c
2312 2320
@@ -2584,6 +2592,7 @@ F: drivers/net/wireless/hostap/
2584 2592
2585HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER 2593HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
2586M: Carlos Corbacho <carlos@strangeworlds.co.uk> 2594M: Carlos Corbacho <carlos@strangeworlds.co.uk>
2595L: platform-driver-x86@vger.kernel.org
2587S: Odd Fixes 2596S: Odd Fixes
2588F: drivers/platform/x86/tc1100-wmi.c 2597F: drivers/platform/x86/tc1100-wmi.c
2589 2598
@@ -2794,7 +2803,7 @@ F: drivers/video/i810/
2794 2803
2795INTEL MENLOW THERMAL DRIVER 2804INTEL MENLOW THERMAL DRIVER
2796M: Sujith Thomas <sujith.thomas@intel.com> 2805M: Sujith Thomas <sujith.thomas@intel.com>
2797L: linux-acpi@vger.kernel.org 2806L: platform-driver-x86@vger.kernel.org
2798W: http://www.lesswatts.org/projects/acpi/ 2807W: http://www.lesswatts.org/projects/acpi/
2799S: Supported 2808S: Supported
2800F: drivers/platform/x86/intel_menlow.c 2809F: drivers/platform/x86/intel_menlow.c
@@ -3660,6 +3669,7 @@ F: drivers/char/mxser.*
3660 3669
3661MSI LAPTOP SUPPORT 3670MSI LAPTOP SUPPORT
3662M: Lennart Poettering <mzxreary@0pointer.de> 3671M: Lennart Poettering <mzxreary@0pointer.de>
3672L: platform-driver-x86@vger.kernel.org
3663W: https://tango.0pointer.de/mailman/listinfo/s270-linux 3673W: https://tango.0pointer.de/mailman/listinfo/s270-linux
3664W: http://0pointer.de/lennart/tchibo.html 3674W: http://0pointer.de/lennart/tchibo.html
3665S: Maintained 3675S: Maintained
@@ -3667,6 +3677,7 @@ F: drivers/platform/x86/msi-laptop.c
3667 3677
3668MSI WMI SUPPORT 3678MSI WMI SUPPORT
3669M: Anisse Astier <anisse@astier.eu> 3679M: Anisse Astier <anisse@astier.eu>
3680L: platform-driver-x86@vger.kernel.org
3670S: Supported 3681S: Supported
3671F: drivers/platform/x86/msi-wmi.c 3682F: drivers/platform/x86/msi-wmi.c
3672 3683
@@ -4119,6 +4130,7 @@ F: drivers/i2c/busses/i2c-pasemi.c
4119 4130
4120PANASONIC LAPTOP ACPI EXTRAS DRIVER 4131PANASONIC LAPTOP ACPI EXTRAS DRIVER
4121M: Harald Welte <laforge@gnumonks.org> 4132M: Harald Welte <laforge@gnumonks.org>
4133L: platform-driver-x86@vger.kernel.org
4122S: Maintained 4134S: Maintained
4123F: drivers/platform/x86/panasonic-laptop.c 4135F: drivers/platform/x86/panasonic-laptop.c
4124 4136
@@ -5064,7 +5076,7 @@ F: include/linux/ssb/
5064 5076
5065SONY VAIO CONTROL DEVICE DRIVER 5077SONY VAIO CONTROL DEVICE DRIVER
5066M: Mattia Dongili <malattia@linux.it> 5078M: Mattia Dongili <malattia@linux.it>
5067L: linux-acpi@vger.kernel.org 5079L: platform-driver-x86@vger.kernel.org
5068W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers 5080W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers
5069S: Maintained 5081S: Maintained
5070F: Documentation/laptops/sony-laptop.txt 5082F: Documentation/laptops/sony-laptop.txt
@@ -5270,6 +5282,7 @@ F: arch/xtensa/
5270THINKPAD ACPI EXTRAS DRIVER 5282THINKPAD ACPI EXTRAS DRIVER
5271M: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br> 5283M: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
5272L: ibm-acpi-devel@lists.sourceforge.net 5284L: ibm-acpi-devel@lists.sourceforge.net
5285L: platform-driver-x86@vger.kernel.org
5273W: http://ibm-acpi.sourceforge.net 5286W: http://ibm-acpi.sourceforge.net
5274W: http://thinkwiki.org/wiki/Ibm-acpi 5287W: http://thinkwiki.org/wiki/Ibm-acpi
5275T: git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git 5288T: git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
@@ -5323,10 +5336,12 @@ F: security/tomoyo/
5323 5336
5324TOPSTAR LAPTOP EXTRAS DRIVER 5337TOPSTAR LAPTOP EXTRAS DRIVER
5325M: Herton Ronaldo Krzesinski <herton@mandriva.com.br> 5338M: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
5339L: platform-driver-x86@vger.kernel.org
5326S: Maintained 5340S: Maintained
5327F: drivers/platform/x86/topstar-laptop.c 5341F: drivers/platform/x86/topstar-laptop.c
5328 5342
5329TOSHIBA ACPI EXTRAS DRIVER 5343TOSHIBA ACPI EXTRAS DRIVER
5344L: platform-driver-x86@vger.kernel.org
5330S: Orphan 5345S: Orphan
5331F: drivers/platform/x86/toshiba_acpi.c 5346F: drivers/platform/x86/toshiba_acpi.c
5332 5347
@@ -6054,6 +6069,12 @@ S: Maintained
6054F: Documentation/x86/ 6069F: Documentation/x86/
6055F: arch/x86/ 6070F: arch/x86/
6056 6071
6072X86 PLATFORM DRIVERS
6073M: Matthew Garrett <mjg@redhat.com>
6074L: platform-driver-x86@vger.kernel.org
6075S: Maintained
6076F: drivers/platform/x86
6077
6057XEN HYPERVISOR INTERFACE 6078XEN HYPERVISOR INTERFACE
6058M: Jeremy Fitzhardinge <jeremy@xensource.com> 6079M: Jeremy Fitzhardinge <jeremy@xensource.com>
6059M: Chris Wright <chrisw@sous-sol.org> 6080M: Chris Wright <chrisw@sous-sol.org>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index f526e735c5ab..6848f213eb53 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -79,6 +79,7 @@ config DELL_LAPTOP
79 depends on BACKLIGHT_CLASS_DEVICE 79 depends on BACKLIGHT_CLASS_DEVICE
80 depends on RFKILL || RFKILL = n 80 depends on RFKILL || RFKILL = n
81 depends on POWER_SUPPLY 81 depends on POWER_SUPPLY
82 depends on SERIO_I8042
82 default n 83 default n
83 ---help--- 84 ---help---
84 This driver adds support for rfkill and backlight control to Dell 85 This driver adds support for rfkill and backlight control to Dell
diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c
index ed90082cdf1d..8cb20e45bad6 100644
--- a/drivers/platform/x86/classmate-laptop.c
+++ b/drivers/platform/x86/classmate-laptop.c
@@ -34,6 +34,11 @@ struct cmpc_accel {
34#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 34#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5
35 35
36 36
37#define CMPC_ACCEL_HID "ACCE0000"
38#define CMPC_TABLET_HID "TBLT0000"
39#define CMPC_BL_HID "IPML200"
40#define CMPC_KEYS_HID "FnBT0000"
41
37/* 42/*
38 * Generic input device code. 43 * Generic input device code.
39 */ 44 */
@@ -282,10 +287,9 @@ static int cmpc_accel_remove(struct acpi_device *acpi, int type)
282} 287}
283 288
284static const struct acpi_device_id cmpc_accel_device_ids[] = { 289static const struct acpi_device_id cmpc_accel_device_ids[] = {
285 {"ACCE0000", 0}, 290 {CMPC_ACCEL_HID, 0},
286 {"", 0} 291 {"", 0}
287}; 292};
288MODULE_DEVICE_TABLE(acpi, cmpc_accel_device_ids);
289 293
290static struct acpi_driver cmpc_accel_acpi_driver = { 294static struct acpi_driver cmpc_accel_acpi_driver = {
291 .owner = THIS_MODULE, 295 .owner = THIS_MODULE,
@@ -366,10 +370,9 @@ static int cmpc_tablet_resume(struct acpi_device *acpi)
366} 370}
367 371
368static const struct acpi_device_id cmpc_tablet_device_ids[] = { 372static const struct acpi_device_id cmpc_tablet_device_ids[] = {
369 {"TBLT0000", 0}, 373 {CMPC_TABLET_HID, 0},
370 {"", 0} 374 {"", 0}
371}; 375};
372MODULE_DEVICE_TABLE(acpi, cmpc_tablet_device_ids);
373 376
374static struct acpi_driver cmpc_tablet_acpi_driver = { 377static struct acpi_driver cmpc_tablet_acpi_driver = {
375 .owner = THIS_MODULE, 378 .owner = THIS_MODULE,
@@ -477,17 +480,16 @@ static int cmpc_bl_remove(struct acpi_device *acpi, int type)
477 return 0; 480 return 0;
478} 481}
479 482
480static const struct acpi_device_id cmpc_device_ids[] = { 483static const struct acpi_device_id cmpc_bl_device_ids[] = {
481 {"IPML200", 0}, 484 {CMPC_BL_HID, 0},
482 {"", 0} 485 {"", 0}
483}; 486};
484MODULE_DEVICE_TABLE(acpi, cmpc_device_ids);
485 487
486static struct acpi_driver cmpc_bl_acpi_driver = { 488static struct acpi_driver cmpc_bl_acpi_driver = {
487 .owner = THIS_MODULE, 489 .owner = THIS_MODULE,
488 .name = "cmpc", 490 .name = "cmpc",
489 .class = "cmpc", 491 .class = "cmpc",
490 .ids = cmpc_device_ids, 492 .ids = cmpc_bl_device_ids,
491 .ops = { 493 .ops = {
492 .add = cmpc_bl_add, 494 .add = cmpc_bl_add,
493 .remove = cmpc_bl_remove 495 .remove = cmpc_bl_remove
@@ -540,10 +542,9 @@ static int cmpc_keys_remove(struct acpi_device *acpi, int type)
540} 542}
541 543
542static const struct acpi_device_id cmpc_keys_device_ids[] = { 544static const struct acpi_device_id cmpc_keys_device_ids[] = {
543 {"FnBT0000", 0}, 545 {CMPC_KEYS_HID, 0},
544 {"", 0} 546 {"", 0}
545}; 547};
546MODULE_DEVICE_TABLE(acpi, cmpc_keys_device_ids);
547 548
548static struct acpi_driver cmpc_keys_acpi_driver = { 549static struct acpi_driver cmpc_keys_acpi_driver = {
549 .owner = THIS_MODULE, 550 .owner = THIS_MODULE,
@@ -607,3 +608,13 @@ static void cmpc_exit(void)
607 608
608module_init(cmpc_init); 609module_init(cmpc_init);
609module_exit(cmpc_exit); 610module_exit(cmpc_exit);
611
612static const struct acpi_device_id cmpc_device_ids[] = {
613 {CMPC_ACCEL_HID, 0},
614 {CMPC_TABLET_HID, 0},
615 {CMPC_BL_HID, 0},
616 {CMPC_KEYS_HID, 0},
617 {"", 0}
618};
619
620MODULE_DEVICE_TABLE(acpi, cmpc_device_ids);
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 1a387e79f719..2740b40aad9b 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -26,17 +26,8 @@
26/* 26/*
27 * comapl-laptop.c - Compal laptop support. 27 * comapl-laptop.c - Compal laptop support.
28 * 28 *
29 * This driver exports a few files in /sys/devices/platform/compal-laptop/: 29 * The driver registers itself with the rfkill subsystem and
30 * 30 * the Linux backlight control subsystem.
31 * wlan - wlan subsystem state: contains 0 or 1 (rw)
32 *
33 * bluetooth - Bluetooth subsystem state: contains 0 or 1 (rw)
34 *
35 * raw - raw value taken from embedded controller register (ro)
36 *
37 * In addition to these platform device attributes the driver
38 * registers itself in the Linux backlight control subsystem and is
39 * available to userspace under /sys/class/backlight/compal-laptop/.
40 * 31 *
41 * This driver might work on other laptops produced by Compal. If you 32 * This driver might work on other laptops produced by Compal. If you
42 * want to try it you can pass force=1 as argument to the module which 33 * want to try it you can pass force=1 as argument to the module which
@@ -51,6 +42,7 @@
51#include <linux/dmi.h> 42#include <linux/dmi.h>
52#include <linux/backlight.h> 43#include <linux/backlight.h>
53#include <linux/platform_device.h> 44#include <linux/platform_device.h>
45#include <linux/rfkill.h>
54 46
55#define COMPAL_DRIVER_VERSION "0.2.6" 47#define COMPAL_DRIVER_VERSION "0.2.6"
56 48
@@ -63,6 +55,10 @@
63#define WLAN_MASK 0x01 55#define WLAN_MASK 0x01
64#define BT_MASK 0x02 56#define BT_MASK 0x02
65 57
58static struct rfkill *wifi_rfkill;
59static struct rfkill *bt_rfkill;
60static struct platform_device *compal_device;
61
66static int force; 62static int force;
67module_param(force, bool, 0); 63module_param(force, bool, 0);
68MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); 64MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -88,65 +84,75 @@ static int get_lcd_level(void)
88 return (int) result; 84 return (int) result;
89} 85}
90 86
91static int set_wlan_state(int state) 87static int compal_rfkill_set(void *data, bool blocked)
92{ 88{
89 unsigned long radio = (unsigned long) data;
93 u8 result, value; 90 u8 result, value;
94 91
95 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); 92 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
96 93
97 if ((result & KILLSWITCH_MASK) == 0) 94 if (!blocked)
98 return -EINVAL; 95 value = (u8) (result | radio);
99 else { 96 else
100 if (state) 97 value = (u8) (result & ~radio);
101 value = (u8) (result | WLAN_MASK); 98 ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
102 else
103 value = (u8) (result & ~WLAN_MASK);
104 ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
105 }
106 99
107 return 0; 100 return 0;
108} 101}
109 102
110static int set_bluetooth_state(int state) 103static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
111{ 104{
112 u8 result, value; 105 u8 result;
106 bool hw_blocked;
113 107
114 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); 108 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
115 109
116 if ((result & KILLSWITCH_MASK) == 0) 110 hw_blocked = !(result & KILLSWITCH_MASK);
117 return -EINVAL; 111 rfkill_set_hw_state(rfkill, hw_blocked);
118 else {
119 if (state)
120 value = (u8) (result | BT_MASK);
121 else
122 value = (u8) (result & ~BT_MASK);
123 ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
124 }
125
126 return 0;
127} 112}
128 113
129static int get_wireless_state(int *wlan, int *bluetooth) 114static const struct rfkill_ops compal_rfkill_ops = {
115 .poll = compal_rfkill_poll,
116 .set_block = compal_rfkill_set,
117};
118
119static int setup_rfkill(void)
130{ 120{
131 u8 result; 121 int ret;
132 122
133 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); 123 wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev,
124 RFKILL_TYPE_WLAN, &compal_rfkill_ops,
125 (void *) WLAN_MASK);
126 if (!wifi_rfkill)
127 return -ENOMEM;
134 128
135 if (wlan) { 129 ret = rfkill_register(wifi_rfkill);
136 if ((result & KILLSWITCH_MASK) == 0) 130 if (ret)
137 *wlan = 0; 131 goto err_wifi;
138 else
139 *wlan = result & WLAN_MASK;
140 }
141 132
142 if (bluetooth) { 133 bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev,
143 if ((result & KILLSWITCH_MASK) == 0) 134 RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops,
144 *bluetooth = 0; 135 (void *) BT_MASK);
145 else 136 if (!bt_rfkill) {
146 *bluetooth = (result & BT_MASK) >> 1; 137 ret = -ENOMEM;
138 goto err_allocate_bt;
147 } 139 }
140 ret = rfkill_register(bt_rfkill);
141 if (ret)
142 goto err_register_bt;
148 143
149 return 0; 144 return 0;
145
146err_register_bt:
147 rfkill_destroy(bt_rfkill);
148
149err_allocate_bt:
150 rfkill_unregister(wifi_rfkill);
151
152err_wifi:
153 rfkill_destroy(wifi_rfkill);
154
155 return ret;
150} 156}
151 157
152/* Backlight device stuff */ 158/* Backlight device stuff */
@@ -169,86 +175,6 @@ static struct backlight_ops compalbl_ops = {
169 175
170static struct backlight_device *compalbl_device; 176static struct backlight_device *compalbl_device;
171 177
172/* Platform device */
173
174static ssize_t show_wlan(struct device *dev,
175 struct device_attribute *attr, char *buf)
176{
177 int ret, enabled;
178
179 ret = get_wireless_state(&enabled, NULL);
180 if (ret < 0)
181 return ret;
182
183 return sprintf(buf, "%i\n", enabled);
184}
185
186static ssize_t show_raw(struct device *dev,
187 struct device_attribute *attr, char *buf)
188{
189 u8 result;
190
191 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
192
193 return sprintf(buf, "%i\n", result);
194}
195
196static ssize_t show_bluetooth(struct device *dev,
197 struct device_attribute *attr, char *buf)
198{
199 int ret, enabled;
200
201 ret = get_wireless_state(NULL, &enabled);
202 if (ret < 0)
203 return ret;
204
205 return sprintf(buf, "%i\n", enabled);
206}
207
208static ssize_t store_wlan_state(struct device *dev,
209 struct device_attribute *attr, const char *buf, size_t count)
210{
211 int state, ret;
212
213 if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
214 return -EINVAL;
215
216 ret = set_wlan_state(state);
217 if (ret < 0)
218 return ret;
219
220 return count;
221}
222
223static ssize_t store_bluetooth_state(struct device *dev,
224 struct device_attribute *attr, const char *buf, size_t count)
225{
226 int state, ret;
227
228 if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
229 return -EINVAL;
230
231 ret = set_bluetooth_state(state);
232 if (ret < 0)
233 return ret;
234
235 return count;
236}
237
238static DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth_state);
239static DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan_state);
240static DEVICE_ATTR(raw, 0444, show_raw, NULL);
241
242static struct attribute *compal_attributes[] = {
243 &dev_attr_bluetooth.attr,
244 &dev_attr_wlan.attr,
245 &dev_attr_raw.attr,
246 NULL
247};
248
249static struct attribute_group compal_attribute_group = {
250 .attrs = compal_attributes
251};
252 178
253static struct platform_driver compal_driver = { 179static struct platform_driver compal_driver = {
254 .driver = { 180 .driver = {
@@ -257,8 +183,6 @@ static struct platform_driver compal_driver = {
257 } 183 }
258}; 184};
259 185
260static struct platform_device *compal_device;
261
262/* Initialization */ 186/* Initialization */
263 187
264static int dmi_check_cb(const struct dmi_system_id *id) 188static int dmi_check_cb(const struct dmi_system_id *id)
@@ -310,6 +234,47 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
310 }, 234 },
311 .callback = dmi_check_cb 235 .callback = dmi_check_cb
312 }, 236 },
237 {
238 .ident = "Dell Mini 9",
239 .matches = {
240 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
241 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
242 },
243 .callback = dmi_check_cb
244 },
245 {
246 .ident = "Dell Mini 10",
247 .matches = {
248 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
249 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
250 },
251 .callback = dmi_check_cb
252 },
253 {
254 .ident = "Dell Mini 10v",
255 .matches = {
256 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
257 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
258 },
259 .callback = dmi_check_cb
260 },
261 {
262 .ident = "Dell Inspiron 11z",
263 .matches = {
264 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
265 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
266 },
267 .callback = dmi_check_cb
268 },
269 {
270 .ident = "Dell Mini 12",
271 .matches = {
272 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
273 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
274 },
275 .callback = dmi_check_cb
276 },
277
313 { } 278 { }
314}; 279};
315 280
@@ -348,23 +313,21 @@ static int __init compal_init(void)
348 313
349 ret = platform_device_add(compal_device); 314 ret = platform_device_add(compal_device);
350 if (ret) 315 if (ret)
351 goto fail_platform_device1; 316 goto fail_platform_device;
352 317
353 ret = sysfs_create_group(&compal_device->dev.kobj, 318 ret = setup_rfkill();
354 &compal_attribute_group);
355 if (ret) 319 if (ret)
356 goto fail_platform_device2; 320 goto fail_rfkill;
357 321
358 printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION 322 printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION
359 " successfully loaded.\n"); 323 " successfully loaded.\n");
360 324
361 return 0; 325 return 0;
362 326
363fail_platform_device2: 327fail_rfkill:
364
365 platform_device_del(compal_device); 328 platform_device_del(compal_device);
366 329
367fail_platform_device1: 330fail_platform_device:
368 331
369 platform_device_put(compal_device); 332 platform_device_put(compal_device);
370 333
@@ -382,10 +345,13 @@ fail_backlight:
382static void __exit compal_cleanup(void) 345static void __exit compal_cleanup(void)
383{ 346{
384 347
385 sysfs_remove_group(&compal_device->dev.kobj, &compal_attribute_group);
386 platform_device_unregister(compal_device); 348 platform_device_unregister(compal_device);
387 platform_driver_unregister(&compal_driver); 349 platform_driver_unregister(&compal_driver);
388 backlight_device_unregister(compalbl_device); 350 backlight_device_unregister(compalbl_device);
351 rfkill_unregister(wifi_rfkill);
352 rfkill_destroy(wifi_rfkill);
353 rfkill_unregister(bt_rfkill);
354 rfkill_destroy(bt_rfkill);
389 355
390 printk(KERN_INFO "compal-laptop: driver unloaded.\n"); 356 printk(KERN_INFO "compal-laptop: driver unloaded.\n");
391} 357}
@@ -403,3 +369,8 @@ MODULE_ALIAS("dmi:*:rnIFL90:rvrREFERENCE:*");
403MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*"); 369MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*");
404MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*"); 370MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*");
405MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*"); 371MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*");
372MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*");
373MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*");
374MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*");
375MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1110:*");
376MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1210:*");
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 3780994dc8f2..b7f4d2705916 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -22,6 +22,8 @@
22#include <linux/rfkill.h> 22#include <linux/rfkill.h>
23#include <linux/power_supply.h> 23#include <linux/power_supply.h>
24#include <linux/acpi.h> 24#include <linux/acpi.h>
25#include <linux/mm.h>
26#include <linux/i8042.h>
25#include "../../firmware/dcdbas.h" 27#include "../../firmware/dcdbas.h"
26 28
27#define BRIGHTNESS_TOKEN 0x7d 29#define BRIGHTNESS_TOKEN 0x7d
@@ -79,9 +81,73 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
79 DMI_MATCH(DMI_CHASSIS_TYPE, "8"), 81 DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
80 }, 82 },
81 }, 83 },
84 {
85 .ident = "Dell Computer Corporation",
86 .matches = {
87 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
88 DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
89 },
90 },
82 { } 91 { }
83}; 92};
84 93
94static struct dmi_system_id __devinitdata dell_blacklist[] = {
95 /* Supported by compal-laptop */
96 {
97 .ident = "Dell Mini 9",
98 .matches = {
99 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
100 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
101 },
102 },
103 {
104 .ident = "Dell Mini 10",
105 .matches = {
106 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
107 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
108 },
109 },
110 {
111 .ident = "Dell Mini 10v",
112 .matches = {
113 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
114 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
115 },
116 },
117 {
118 .ident = "Dell Inspiron 11z",
119 .matches = {
120 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
121 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
122 },
123 },
124 {
125 .ident = "Dell Mini 12",
126 .matches = {
127 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
128 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
129 },
130 },
131 {}
132};
133
134static struct calling_interface_buffer *buffer;
135struct page *bufferpage;
136DEFINE_MUTEX(buffer_mutex);
137
138static int hwswitch_state;
139
140static void get_buffer(void)
141{
142 mutex_lock(&buffer_mutex);
143 memset(buffer, 0, sizeof(struct calling_interface_buffer));
144}
145
146static void release_buffer(void)
147{
148 mutex_unlock(&buffer_mutex);
149}
150
85static void __init parse_da_table(const struct dmi_header *dm) 151static void __init parse_da_table(const struct dmi_header *dm)
86{ 152{
87 /* Final token is a terminator, so we don't want to copy it */ 153 /* Final token is a terminator, so we don't want to copy it */
@@ -160,6 +226,8 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
160/* Derived from information in DellWirelessCtl.cpp: 226/* Derived from information in DellWirelessCtl.cpp:
161 Class 17, select 11 is radio control. It returns an array of 32-bit values. 227 Class 17, select 11 is radio control. It returns an array of 32-bit values.
162 228
229 Input byte 0 = 0: Wireless information
230
163 result[0]: return code 231 result[0]: return code
164 result[1]: 232 result[1]:
165 Bit 0: Hardware switch supported 233 Bit 0: Hardware switch supported
@@ -180,33 +248,62 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
180 Bits 20-31: Reserved 248 Bits 20-31: Reserved
181 result[2]: NVRAM size in bytes 249 result[2]: NVRAM size in bytes
182 result[3]: NVRAM format version number 250 result[3]: NVRAM format version number
251
252 Input byte 0 = 2: Wireless switch configuration
253 result[0]: return code
254 result[1]:
255 Bit 0: Wifi controlled by switch
256 Bit 1: Bluetooth controlled by switch
257 Bit 2: WWAN controlled by switch
258 Bits 3-6: Reserved
259 Bit 7: Wireless switch config locked
260 Bit 8: Wifi locator enabled
261 Bits 9-14: Reserved
262 Bit 15: Wifi locator setting locked
263 Bits 16-31: Reserved
183*/ 264*/
184 265
185static int dell_rfkill_set(void *data, bool blocked) 266static int dell_rfkill_set(void *data, bool blocked)
186{ 267{
187 struct calling_interface_buffer buffer;
188 int disable = blocked ? 1 : 0; 268 int disable = blocked ? 1 : 0;
189 unsigned long radio = (unsigned long)data; 269 unsigned long radio = (unsigned long)data;
270 int hwswitch_bit = (unsigned long)data - 1;
271 int ret = 0;
272
273 get_buffer();
274 dell_send_request(buffer, 17, 11);
275
276 /* If the hardware switch controls this radio, and the hardware
277 switch is disabled, don't allow changing the software state */
278 if ((hwswitch_state & BIT(hwswitch_bit)) &&
279 !(buffer->output[1] & BIT(16))) {
280 ret = -EINVAL;
281 goto out;
282 }
190 283
191 memset(&buffer, 0, sizeof(struct calling_interface_buffer)); 284 buffer->input[0] = (1 | (radio<<8) | (disable << 16));
192 buffer.input[0] = (1 | (radio<<8) | (disable << 16)); 285 dell_send_request(buffer, 17, 11);
193 dell_send_request(&buffer, 17, 11);
194 286
195 return 0; 287out:
288 release_buffer();
289 return ret;
196} 290}
197 291
198static void dell_rfkill_query(struct rfkill *rfkill, void *data) 292static void dell_rfkill_query(struct rfkill *rfkill, void *data)
199{ 293{
200 struct calling_interface_buffer buffer;
201 int status; 294 int status;
202 int bit = (unsigned long)data + 16; 295 int bit = (unsigned long)data + 16;
296 int hwswitch_bit = (unsigned long)data - 1;
203 297
204 memset(&buffer, 0, sizeof(struct calling_interface_buffer)); 298 get_buffer();
205 dell_send_request(&buffer, 17, 11); 299 dell_send_request(buffer, 17, 11);
206 status = buffer.output[1]; 300 status = buffer->output[1];
301 release_buffer();
207 302
208 rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); 303 rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));
209 rfkill_set_hw_state(rfkill, !(status & BIT(16))); 304
305 if (hwswitch_state & (BIT(hwswitch_bit)))
306 rfkill_set_hw_state(rfkill, !(status & BIT(16)));
210} 307}
211 308
212static const struct rfkill_ops dell_rfkill_ops = { 309static const struct rfkill_ops dell_rfkill_ops = {
@@ -214,15 +311,36 @@ static const struct rfkill_ops dell_rfkill_ops = {
214 .query = dell_rfkill_query, 311 .query = dell_rfkill_query,
215}; 312};
216 313
314static void dell_update_rfkill(struct work_struct *ignored)
315{
316 if (wifi_rfkill)
317 dell_rfkill_query(wifi_rfkill, (void *)1);
318 if (bluetooth_rfkill)
319 dell_rfkill_query(bluetooth_rfkill, (void *)2);
320 if (wwan_rfkill)
321 dell_rfkill_query(wwan_rfkill, (void *)3);
322}
323static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
324
325
217static int __init dell_setup_rfkill(void) 326static int __init dell_setup_rfkill(void)
218{ 327{
219 struct calling_interface_buffer buffer;
220 int status; 328 int status;
221 int ret; 329 int ret;
222 330
223 memset(&buffer, 0, sizeof(struct calling_interface_buffer)); 331 if (dmi_check_system(dell_blacklist)) {
224 dell_send_request(&buffer, 17, 11); 332 printk(KERN_INFO "dell-laptop: Blacklisted hardware detected - "
225 status = buffer.output[1]; 333 "not enabling rfkill\n");
334 return 0;
335 }
336
337 get_buffer();
338 dell_send_request(buffer, 17, 11);
339 status = buffer->output[1];
340 buffer->input[0] = 0x2;
341 dell_send_request(buffer, 17, 11);
342 hwswitch_state = buffer->output[1];
343 release_buffer();
226 344
227 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { 345 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
228 wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, 346 wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
@@ -298,39 +416,49 @@ static void dell_cleanup_rfkill(void)
298 416
299static int dell_send_intensity(struct backlight_device *bd) 417static int dell_send_intensity(struct backlight_device *bd)
300{ 418{
301 struct calling_interface_buffer buffer; 419 int ret = 0;
302 420
303 memset(&buffer, 0, sizeof(struct calling_interface_buffer)); 421 get_buffer();
304 buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN); 422 buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
305 buffer.input[1] = bd->props.brightness; 423 buffer->input[1] = bd->props.brightness;
306 424
307 if (buffer.input[0] == -1) 425 if (buffer->input[0] == -1) {
308 return -ENODEV; 426 ret = -ENODEV;
427 goto out;
428 }
309 429
310 if (power_supply_is_system_supplied() > 0) 430 if (power_supply_is_system_supplied() > 0)
311 dell_send_request(&buffer, 1, 2); 431 dell_send_request(buffer, 1, 2);
312 else 432 else
313 dell_send_request(&buffer, 1, 1); 433 dell_send_request(buffer, 1, 1);
314 434
435out:
436 release_buffer();
315 return 0; 437 return 0;
316} 438}
317 439
318static int dell_get_intensity(struct backlight_device *bd) 440static int dell_get_intensity(struct backlight_device *bd)
319{ 441{
320 struct calling_interface_buffer buffer; 442 int ret = 0;
321 443
322 memset(&buffer, 0, sizeof(struct calling_interface_buffer)); 444 get_buffer();
323 buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN); 445 buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
324 446
325 if (buffer.input[0] == -1) 447 if (buffer->input[0] == -1) {
326 return -ENODEV; 448 ret = -ENODEV;
449 goto out;
450 }
327 451
328 if (power_supply_is_system_supplied() > 0) 452 if (power_supply_is_system_supplied() > 0)
329 dell_send_request(&buffer, 0, 2); 453 dell_send_request(buffer, 0, 2);
330 else 454 else
331 dell_send_request(&buffer, 0, 1); 455 dell_send_request(buffer, 0, 1);
332 456
333 return buffer.output[1]; 457out:
458 release_buffer();
459 if (ret)
460 return ret;
461 return buffer->output[1];
334} 462}
335 463
336static struct backlight_ops dell_ops = { 464static struct backlight_ops dell_ops = {
@@ -338,9 +466,32 @@ static struct backlight_ops dell_ops = {
338 .update_status = dell_send_intensity, 466 .update_status = dell_send_intensity,
339}; 467};
340 468
469bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
470 struct serio *port)
471{
472 static bool extended;
473
474 if (str & 0x20)
475 return false;
476
477 if (unlikely(data == 0xe0)) {
478 extended = true;
479 return false;
480 } else if (unlikely(extended)) {
481 switch (data) {
482 case 0x8:
483 schedule_delayed_work(&dell_rfkill_work,
484 round_jiffies_relative(HZ));
485 break;
486 }
487 extended = false;
488 }
489
490 return false;
491}
492
341static int __init dell_init(void) 493static int __init dell_init(void)
342{ 494{
343 struct calling_interface_buffer buffer;
344 int max_intensity = 0; 495 int max_intensity = 0;
345 int ret; 496 int ret;
346 497
@@ -366,6 +517,17 @@ static int __init dell_init(void)
366 if (ret) 517 if (ret)
367 goto fail_platform_device2; 518 goto fail_platform_device2;
368 519
520 /*
521 * Allocate buffer below 4GB for SMI data--only 32-bit physical addr
522 * is passed to SMI handler.
523 */
524 bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32);
525
526 if (!bufferpage)
527 goto fail_buffer;
528 buffer = page_address(bufferpage);
529 mutex_init(&buffer_mutex);
530
369 ret = dell_setup_rfkill(); 531 ret = dell_setup_rfkill();
370 532
371 if (ret) { 533 if (ret) {
@@ -373,6 +535,13 @@ static int __init dell_init(void)
373 goto fail_rfkill; 535 goto fail_rfkill;
374 } 536 }
375 537
538 ret = i8042_install_filter(dell_laptop_i8042_filter);
539 if (ret) {
540 printk(KERN_WARNING
541 "dell-laptop: Unable to install key filter\n");
542 goto fail_filter;
543 }
544
376#ifdef CONFIG_ACPI 545#ifdef CONFIG_ACPI
377 /* In the event of an ACPI backlight being available, don't 546 /* In the event of an ACPI backlight being available, don't
378 * register the platform controller. 547 * register the platform controller.
@@ -381,13 +550,13 @@ static int __init dell_init(void)
381 return 0; 550 return 0;
382#endif 551#endif
383 552
384 memset(&buffer, 0, sizeof(struct calling_interface_buffer)); 553 get_buffer();
385 buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN); 554 buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
386 555 if (buffer->input[0] != -1) {
387 if (buffer.input[0] != -1) { 556 dell_send_request(buffer, 0, 2);
388 dell_send_request(&buffer, 0, 2); 557 max_intensity = buffer->output[3];
389 max_intensity = buffer.output[3];
390 } 558 }
559 release_buffer();
391 560
392 if (max_intensity) { 561 if (max_intensity) {
393 dell_backlight_device = backlight_device_register( 562 dell_backlight_device = backlight_device_register(
@@ -410,8 +579,12 @@ static int __init dell_init(void)
410 return 0; 579 return 0;
411 580
412fail_backlight: 581fail_backlight:
582 i8042_remove_filter(dell_laptop_i8042_filter);
583fail_filter:
413 dell_cleanup_rfkill(); 584 dell_cleanup_rfkill();
414fail_rfkill: 585fail_rfkill:
586 free_page((unsigned long)bufferpage);
587fail_buffer:
415 platform_device_del(platform_device); 588 platform_device_del(platform_device);
416fail_platform_device2: 589fail_platform_device2:
417 platform_device_put(platform_device); 590 platform_device_put(platform_device);
@@ -424,8 +597,16 @@ fail_platform_driver:
424 597
425static void __exit dell_exit(void) 598static void __exit dell_exit(void)
426{ 599{
600 cancel_delayed_work_sync(&dell_rfkill_work);
601 i8042_remove_filter(dell_laptop_i8042_filter);
427 backlight_device_unregister(dell_backlight_device); 602 backlight_device_unregister(dell_backlight_device);
428 dell_cleanup_rfkill(); 603 dell_cleanup_rfkill();
604 if (platform_device) {
605 platform_device_del(platform_device);
606 platform_driver_unregister(&platform_driver);
607 }
608 kfree(da_tokens);
609 free_page((unsigned long)buffer);
429} 610}
430 611
431module_init(dell_init); 612module_init(dell_init);
@@ -435,3 +616,4 @@ MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
435MODULE_DESCRIPTION("Dell laptop driver"); 616MODULE_DESCRIPTION("Dell laptop driver");
436MODULE_LICENSE("GPL"); 617MODULE_LICENSE("GPL");
437MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*"); 618MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*");
619MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*");
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index ad4c414dbfbc..3aa57da8b43b 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -89,6 +89,7 @@ static struct key_entry hp_wmi_keymap[] = {
89 {KE_KEY, 0x20e6, KEY_PROG1}, 89 {KE_KEY, 0x20e6, KEY_PROG1},
90 {KE_KEY, 0x2142, KEY_MEDIA}, 90 {KE_KEY, 0x2142, KEY_MEDIA},
91 {KE_KEY, 0x213b, KEY_INFO}, 91 {KE_KEY, 0x213b, KEY_INFO},
92 {KE_KEY, 0x2169, KEY_DIRECTION},
92 {KE_KEY, 0x231b, KEY_HELP}, 93 {KE_KEY, 0x231b, KEY_HELP},
93 {KE_END, 0} 94 {KE_END, 0}
94}; 95};
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 77bf5d8f893a..26c211724acf 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -46,6 +46,7 @@
46#include <linux/backlight.h> 46#include <linux/backlight.h>
47#include <linux/platform_device.h> 47#include <linux/platform_device.h>
48#include <linux/rfkill.h> 48#include <linux/rfkill.h>
49#include <linux/input.h>
49 50
50#include <asm/uaccess.h> 51#include <asm/uaccess.h>
51 52
@@ -62,9 +63,10 @@ MODULE_LICENSE("GPL");
62 63
63/* Toshiba ACPI method paths */ 64/* Toshiba ACPI method paths */
64#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM" 65#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
65#define METHOD_HCI_1 "\\_SB_.VALD.GHCI" 66#define TOSH_INTERFACE_1 "\\_SB_.VALD"
66#define METHOD_HCI_2 "\\_SB_.VALZ.GHCI" 67#define TOSH_INTERFACE_2 "\\_SB_.VALZ"
67#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX" 68#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
69#define GHCI_METHOD ".GHCI"
68 70
69/* Toshiba HCI interface definitions 71/* Toshiba HCI interface definitions
70 * 72 *
@@ -116,6 +118,36 @@ static const struct acpi_device_id toshiba_device_ids[] = {
116}; 118};
117MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); 119MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
118 120
121struct key_entry {
122 char type;
123 u16 code;
124 u16 keycode;
125};
126
127enum {KE_KEY, KE_END};
128
129static struct key_entry toshiba_acpi_keymap[] = {
130 {KE_KEY, 0x101, KEY_MUTE},
131 {KE_KEY, 0x13b, KEY_COFFEE},
132 {KE_KEY, 0x13c, KEY_BATTERY},
133 {KE_KEY, 0x13d, KEY_SLEEP},
134 {KE_KEY, 0x13e, KEY_SUSPEND},
135 {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE},
136 {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN},
137 {KE_KEY, 0x141, KEY_BRIGHTNESSUP},
138 {KE_KEY, 0x142, KEY_WLAN},
139 {KE_KEY, 0x143, KEY_PROG1},
140 {KE_KEY, 0xb05, KEY_PROG2},
141 {KE_KEY, 0xb06, KEY_WWW},
142 {KE_KEY, 0xb07, KEY_MAIL},
143 {KE_KEY, 0xb30, KEY_STOP},
144 {KE_KEY, 0xb31, KEY_PREVIOUSSONG},
145 {KE_KEY, 0xb32, KEY_NEXTSONG},
146 {KE_KEY, 0xb33, KEY_PLAYPAUSE},
147 {KE_KEY, 0xb5a, KEY_MEDIA},
148 {KE_END, 0, 0},
149};
150
119/* utility 151/* utility
120 */ 152 */
121 153
@@ -251,6 +283,8 @@ static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result)
251struct toshiba_acpi_dev { 283struct toshiba_acpi_dev {
252 struct platform_device *p_dev; 284 struct platform_device *p_dev;
253 struct rfkill *bt_rfk; 285 struct rfkill *bt_rfk;
286 struct input_dev *hotkey_dev;
287 acpi_handle handle;
254 288
255 const char *bt_name; 289 const char *bt_name;
256 290
@@ -711,8 +745,159 @@ static struct backlight_ops toshiba_backlight_data = {
711 .update_status = set_lcd_status, 745 .update_status = set_lcd_status,
712}; 746};
713 747
748static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code)
749{
750 struct key_entry *key;
751
752 for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
753 if (code == key->code)
754 return key;
755
756 return NULL;
757}
758
759static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code)
760{
761 struct key_entry *key;
762
763 for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
764 if (code == key->keycode && key->type == KE_KEY)
765 return key;
766
767 return NULL;
768}
769
770static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode,
771 int *keycode)
772{
773 struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
774
775 if (key && key->type == KE_KEY) {
776 *keycode = key->keycode;
777 return 0;
778 }
779
780 return -EINVAL;
781}
782
783static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode,
784 int keycode)
785{
786 struct key_entry *key;
787 int old_keycode;
788
789 if (keycode < 0 || keycode > KEY_MAX)
790 return -EINVAL;
791
792 key = toshiba_acpi_get_entry_by_scancode(scancode);
793 if (key && key->type == KE_KEY) {
794 old_keycode = key->keycode;
795 key->keycode = keycode;
796 set_bit(keycode, dev->keybit);
797 if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
798 clear_bit(old_keycode, dev->keybit);
799 return 0;
800 }
801
802 return -EINVAL;
803}
804
805static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
806{
807 u32 hci_result, value;
808 struct key_entry *key;
809
810 if (event != 0x80)
811 return;
812 do {
813 hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
814 if (hci_result == HCI_SUCCESS) {
815 if (value == 0x100)
816 continue;
817 else if (value & 0x80) {
818 key = toshiba_acpi_get_entry_by_scancode
819 (value & ~0x80);
820 if (!key) {
821 printk(MY_INFO "Unknown key %x\n",
822 value & ~0x80);
823 continue;
824 }
825 input_report_key(toshiba_acpi.hotkey_dev,
826 key->keycode, 1);
827 input_sync(toshiba_acpi.hotkey_dev);
828 input_report_key(toshiba_acpi.hotkey_dev,
829 key->keycode, 0);
830 input_sync(toshiba_acpi.hotkey_dev);
831 }
832 } else if (hci_result == HCI_NOT_SUPPORTED) {
833 /* This is a workaround for an unresolved issue on
834 * some machines where system events sporadically
835 * become disabled. */
836 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
837 printk(MY_NOTICE "Re-enabled hotkeys\n");
838 }
839 } while (hci_result != HCI_EMPTY);
840}
841
842static int toshiba_acpi_setup_keyboard(char *device)
843{
844 acpi_status status;
845 acpi_handle handle;
846 int result;
847 const struct key_entry *key;
848
849 status = acpi_get_handle(NULL, device, &handle);
850 if (ACPI_FAILURE(status)) {
851 printk(MY_INFO "Unable to get notification device\n");
852 return -ENODEV;
853 }
854
855 toshiba_acpi.handle = handle;
856
857 status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
858 if (ACPI_FAILURE(status)) {
859 printk(MY_INFO "Unable to enable hotkeys\n");
860 return -ENODEV;
861 }
862
863 status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
864 toshiba_acpi_notify, NULL);
865 if (ACPI_FAILURE(status)) {
866 printk(MY_INFO "Unable to install hotkey notification\n");
867 return -ENODEV;
868 }
869
870 toshiba_acpi.hotkey_dev = input_allocate_device();
871 if (!toshiba_acpi.hotkey_dev) {
872 printk(MY_INFO "Unable to register input device\n");
873 return -ENOMEM;
874 }
875
876 toshiba_acpi.hotkey_dev->name = "Toshiba input device";
877 toshiba_acpi.hotkey_dev->phys = device;
878 toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
879 toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
880 toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
881
882 for (key = toshiba_acpi_keymap; key->type != KE_END; key++) {
883 set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit);
884 set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit);
885 }
886
887 result = input_register_device(toshiba_acpi.hotkey_dev);
888 if (result) {
889 printk(MY_INFO "Unable to register input device\n");
890 return result;
891 }
892
893 return 0;
894}
895
714static void toshiba_acpi_exit(void) 896static void toshiba_acpi_exit(void)
715{ 897{
898 if (toshiba_acpi.hotkey_dev)
899 input_unregister_device(toshiba_acpi.hotkey_dev);
900
716 if (toshiba_acpi.bt_rfk) { 901 if (toshiba_acpi.bt_rfk) {
717 rfkill_unregister(toshiba_acpi.bt_rfk); 902 rfkill_unregister(toshiba_acpi.bt_rfk);
718 rfkill_destroy(toshiba_acpi.bt_rfk); 903 rfkill_destroy(toshiba_acpi.bt_rfk);
@@ -726,6 +911,9 @@ static void toshiba_acpi_exit(void)
726 if (toshiba_proc_dir) 911 if (toshiba_proc_dir)
727 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); 912 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
728 913
914 acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
915 toshiba_acpi_notify);
916
729 platform_device_unregister(toshiba_acpi.p_dev); 917 platform_device_unregister(toshiba_acpi.p_dev);
730 918
731 return; 919 return;
@@ -742,11 +930,15 @@ static int __init toshiba_acpi_init(void)
742 return -ENODEV; 930 return -ENODEV;
743 931
744 /* simple device detection: look for HCI method */ 932 /* simple device detection: look for HCI method */
745 if (is_valid_acpi_path(METHOD_HCI_1)) 933 if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
746 method_hci = METHOD_HCI_1; 934 method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
747 else if (is_valid_acpi_path(METHOD_HCI_2)) 935 if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
748 method_hci = METHOD_HCI_2; 936 printk(MY_INFO "Unable to activate hotkeys\n");
749 else 937 } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
938 method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
939 if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
940 printk(MY_INFO "Unable to activate hotkeys\n");
941 } else
750 return -ENODEV; 942 return -ENODEV;
751 943
752 printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n", 944 printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",