aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-08-06 16:26:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-08-06 16:26:15 -0400
commit2560540b78b48c8050f56e8ff5903c11a4f7a16e (patch)
treefca860f19ef6845e0d61dad8d8e3648c059b4ecd /drivers
parent45a05f9488911851f7a5c536df80b41f0105caf0 (diff)
parent15b956a0b5651bbb1217ec374fdd67291dabb2af (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: (38 commits) acer-wmi: support Lenovo ideapad S205 wifi switch acerhdf.c: spaces in aliased changed to * platform-drivers-x86: ideapad-laptop: add missing ideapad_input_exit in ideapad_acpi_add error path x86 driver: fix typo in TDP override enabling Platform: fix samsung-laptop DMI identification for N150/N210/220/N230 dell-wmi: Add keys for Dell XPS L502X platform-drivers-x86: samsung-q10: make dmi_check_callback return 1 Platform: Samsung Q10 backlight driver platform-drivers-x86: intel_scu_ipc: convert to DEFINE_PCI_DEVICE_TABLE platform-drivers-x86: intel_rar_register: convert to DEFINE_PCI_DEVICE_TABLE platform-drivers-x86: intel_menlow: add missing return AE_OK for intel_menlow_register_sensor() platform-drivers-x86: intel_mid_thermal: fix memory leak platform-drivers-x86: msi-wmi: add missing sparse_keymap_free in msi_wmi_init error path Samsung Laptop platform driver: support N510 asus-wmi: add uwb rfkill support asus-wmi: add gps rfkill support asus-wmi: add CWAP support and clarify the meaning of WAPF bits asus-wmi: return proper value in store_cpufv() asus-wmi: check for temp1 presence asus-wmi: add thermal sensor ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/x86/Kconfig8
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c40
-rw-r--r--drivers/platform/x86/acerhdf.c13
-rw-r--r--drivers/platform/x86/asus-laptop.c9
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c27
-rw-r--r--drivers/platform/x86/asus-wmi.c239
-rw-r--r--drivers/platform/x86/asus-wmi.h7
-rw-r--r--drivers/platform/x86/dell-laptop.c1
-rw-r--r--drivers/platform/x86/dell-wmi.c10
-rw-r--r--drivers/platform/x86/eeepc-wmi.c27
-rw-r--r--drivers/platform/x86/ideapad-laptop.c195
-rw-r--r--drivers/platform/x86/intel_ips.c4
-rw-r--r--drivers/platform/x86/intel_menlow.c2
-rw-r--r--drivers/platform/x86/intel_mid_thermal.c26
-rw-r--r--drivers/platform/x86/intel_rar_register.c4
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c2
-rw-r--r--drivers/platform/x86/msi-laptop.c10
-rw-r--r--drivers/platform/x86/msi-wmi.c1
-rw-r--r--drivers/platform/x86/samsung-laptop.c20
-rw-r--r--drivers/platform/x86/samsung-q10.c196
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c11
22 files changed, 769 insertions, 84 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 45e0191c35dd..1e88d4785321 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -769,4 +769,12 @@ config INTEL_OAKTRAIL
769 enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y 769 enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
770 here; it will only load on supported platforms. 770 here; it will only load on supported platforms.
771 771
772config SAMSUNG_Q10
773 tristate "Samsung Q10 Extras"
774 depends on SERIO_I8042
775 select BACKLIGHT_CLASS_DEVICE
776 ---help---
777 This driver provides support for backlight control on Samsung Q10
778 and related laptops, including Dell Latitude X200.
779
772endif # X86_PLATFORM_DEVICES 780endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index afc1f832aa67..293a320d9faa 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o
44obj-$(CONFIG_MXM_WMI) += mxm-wmi.o 44obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
45obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o 45obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o
46obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o 46obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
47obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index e1c4938b301b..af2bb20cb2fb 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -99,6 +99,7 @@ enum acer_wmi_event_ids {
99static const struct key_entry acer_wmi_keymap[] = { 99static const struct key_entry acer_wmi_keymap[] = {
100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ 100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
101 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */ 101 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */
102 {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */
102 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */ 103 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */
103 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */ 104 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */
104 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */ 105 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */
@@ -304,6 +305,10 @@ static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
304 .wireless = 2, 305 .wireless = 2,
305}; 306};
306 307
308static struct quirk_entry quirk_lenovo_ideapad_s205 = {
309 .wireless = 3,
310};
311
307/* The Aspire One has a dummy ACPI-WMI interface - disable it */ 312/* The Aspire One has a dummy ACPI-WMI interface - disable it */
308static struct dmi_system_id __devinitdata acer_blacklist[] = { 313static struct dmi_system_id __devinitdata acer_blacklist[] = {
309 { 314 {
@@ -450,6 +455,15 @@ static struct dmi_system_id acer_quirks[] = {
450 }, 455 },
451 .driver_data = &quirk_medion_md_98300, 456 .driver_data = &quirk_medion_md_98300,
452 }, 457 },
458 {
459 .callback = dmi_matched,
460 .ident = "Lenovo Ideapad S205",
461 .matches = {
462 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
463 DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),
464 },
465 .driver_data = &quirk_lenovo_ideapad_s205,
466 },
453 {} 467 {}
454}; 468};
455 469
@@ -542,6 +556,12 @@ struct wmi_interface *iface)
542 return AE_ERROR; 556 return AE_ERROR;
543 *value = result & 0x1; 557 *value = result & 0x1;
544 return AE_OK; 558 return AE_OK;
559 case 3:
560 err = ec_read(0x78, &result);
561 if (err)
562 return AE_ERROR;
563 *value = result & 0x1;
564 return AE_OK;
545 default: 565 default:
546 err = ec_read(0xA, &result); 566 err = ec_read(0xA, &result);
547 if (err) 567 if (err)
@@ -1266,8 +1286,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
1266 acpi_status status; 1286 acpi_status status;
1267 1287
1268 status = get_u32(&state, ACER_CAP_WIRELESS); 1288 status = get_u32(&state, ACER_CAP_WIRELESS);
1269 if (ACPI_SUCCESS(status)) 1289 if (ACPI_SUCCESS(status)) {
1270 rfkill_set_sw_state(wireless_rfkill, !state); 1290 if (quirks->wireless == 3) {
1291 rfkill_set_hw_state(wireless_rfkill, !state);
1292 } else {
1293 rfkill_set_sw_state(wireless_rfkill, !state);
1294 }
1295 }
1271 1296
1272 if (has_cap(ACER_CAP_BLUETOOTH)) { 1297 if (has_cap(ACER_CAP_BLUETOOTH)) {
1273 status = get_u32(&state, ACER_CAP_BLUETOOTH); 1298 status = get_u32(&state, ACER_CAP_BLUETOOTH);
@@ -1400,6 +1425,9 @@ static ssize_t show_bool_threeg(struct device *dev,
1400{ 1425{
1401 u32 result; \ 1426 u32 result; \
1402 acpi_status status; 1427 acpi_status status;
1428
1429 pr_info("This threeg sysfs will be removed in 2012"
1430 " - used by: %s\n", current->comm);
1403 if (wmi_has_guid(WMID_GUID3)) 1431 if (wmi_has_guid(WMID_GUID3))
1404 status = wmid3_get_device_status(&result, 1432 status = wmid3_get_device_status(&result,
1405 ACER_WMID3_GDS_THREEG); 1433 ACER_WMID3_GDS_THREEG);
@@ -1415,8 +1443,10 @@ static ssize_t set_bool_threeg(struct device *dev,
1415{ 1443{
1416 u32 tmp = simple_strtoul(buf, NULL, 10); 1444 u32 tmp = simple_strtoul(buf, NULL, 10);
1417 acpi_status status = set_u32(tmp, ACER_CAP_THREEG); 1445 acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
1418 if (ACPI_FAILURE(status)) 1446 pr_info("This threeg sysfs will be removed in 2012"
1419 return -EINVAL; 1447 " - used by: %s\n", current->comm);
1448 if (ACPI_FAILURE(status))
1449 return -EINVAL;
1420 return count; 1450 return count;
1421} 1451}
1422static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg, 1452static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
@@ -1425,6 +1455,8 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
1425static ssize_t show_interface(struct device *dev, struct device_attribute *attr, 1455static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1426 char *buf) 1456 char *buf)
1427{ 1457{
1458 pr_info("This interface sysfs will be removed in 2012"
1459 " - used by: %s\n", current->comm);
1428 switch (interface->type) { 1460 switch (interface->type) {
1429 case ACER_AMW0: 1461 case ACER_AMW0:
1430 return sprintf(buf, "AMW0\n"); 1462 return sprintf(buf, "AMW0\n");
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index fca3489218b7..760c6d7624fe 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -182,6 +182,7 @@ static const struct bios_settings_t bios_tbl[] = {
182 {"Acer", "Aspire 1810T", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, 182 {"Acer", "Aspire 1810T", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
183 {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, 183 {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
184 {"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, 184 {"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
185 {"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
185 /* Acer 531 */ 186 /* Acer 531 */
186 {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} }, 187 {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
187 /* Gateway */ 188 /* Gateway */
@@ -703,15 +704,15 @@ MODULE_LICENSE("GPL");
703MODULE_AUTHOR("Peter Feuerer"); 704MODULE_AUTHOR("Peter Feuerer");
704MODULE_DESCRIPTION("Aspire One temperature and fan driver"); 705MODULE_DESCRIPTION("Aspire One temperature and fan driver");
705MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); 706MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
706MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:"); 707MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
707MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:"); 708MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
708MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:"); 709MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
709MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); 710MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
710MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:"); 711MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
711MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); 712MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
712MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); 713MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOA*:");
713MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:"); 714MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
714MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMA*:"); 715MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
715 716
716module_init(acerhdf_init); 717module_init(acerhdf_init);
717module_exit(acerhdf_exit); 718module_exit(acerhdf_exit);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index d65df92e2acc..fa6d7ec68b26 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -70,11 +70,10 @@ MODULE_LICENSE("GPL");
70 * WAPF defines the behavior of the Fn+Fx wlan key 70 * WAPF defines the behavior of the Fn+Fx wlan key
71 * The significance of values is yet to be found, but 71 * The significance of values is yet to be found, but
72 * most of the time: 72 * most of the time:
73 * 0x0 will do nothing 73 * Bit | Bluetooth | WLAN
74 * 0x1 will allow to control the device with Fn+Fx key. 74 * 0 | Hardware | Hardware
75 * 0x4 will send an ACPI event (0x88) while pressing the Fn+Fx key 75 * 1 | Hardware | Software
76 * 0x5 like 0x1 or 0x4 76 * 4 | Software | Software
77 * So, if something doesn't work as you want, just try other values =)
78 */ 77 */
79static uint wapf = 1; 78static uint wapf = 1;
80module_param(wapf, uint, 0444); 79module_param(wapf, uint, 0444);
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 0580d99b0798..b0859d4183e8 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -38,6 +38,24 @@ MODULE_LICENSE("GPL");
38 38
39MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID); 39MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
40 40
41/*
42 * WAPF defines the behavior of the Fn+Fx wlan key
43 * The significance of values is yet to be found, but
44 * most of the time:
45 * Bit | Bluetooth | WLAN
46 * 0 | Hardware | Hardware
47 * 1 | Hardware | Software
48 * 4 | Software | Software
49 */
50static uint wapf;
51module_param(wapf, uint, 0444);
52MODULE_PARM_DESC(wapf, "WAPF value");
53
54static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
55{
56 driver->wapf = wapf;
57}
58
41static const struct key_entry asus_nb_wmi_keymap[] = { 59static const struct key_entry asus_nb_wmi_keymap[] = {
42 { KE_KEY, 0x30, { KEY_VOLUMEUP } }, 60 { KE_KEY, 0x30, { KEY_VOLUMEUP } },
43 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, 61 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
@@ -53,16 +71,16 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
53 { KE_KEY, 0x51, { KEY_WWW } }, 71 { KE_KEY, 0x51, { KEY_WWW } },
54 { KE_KEY, 0x55, { KEY_CALC } }, 72 { KE_KEY, 0x55, { KEY_CALC } },
55 { KE_KEY, 0x5C, { KEY_F15 } }, /* Power Gear key */ 73 { KE_KEY, 0x5C, { KEY_F15 } }, /* Power Gear key */
56 { KE_KEY, 0x5D, { KEY_WLAN } }, 74 { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */
57 { KE_KEY, 0x5E, { KEY_WLAN } }, 75 { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */
58 { KE_KEY, 0x5F, { KEY_WLAN } }, 76 { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */
59 { KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } }, 77 { KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
60 { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, 78 { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
61 { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, 79 { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
62 { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, 80 { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
63 { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, 81 { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
64 { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
65 { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, 82 { KE_KEY, 0x7D, { KEY_BLUETOOTH } },
83 { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
66 { KE_KEY, 0x82, { KEY_CAMERA } }, 84 { KE_KEY, 0x82, { KEY_CAMERA } },
67 { KE_KEY, 0x88, { KEY_RFKILL } }, 85 { KE_KEY, 0x88, { KEY_RFKILL } },
68 { KE_KEY, 0x8A, { KEY_PROG1 } }, 86 { KE_KEY, 0x8A, { KEY_PROG1 } },
@@ -81,6 +99,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
81 .keymap = asus_nb_wmi_keymap, 99 .keymap = asus_nb_wmi_keymap,
82 .input_name = "Asus WMI hotkeys", 100 .input_name = "Asus WMI hotkeys",
83 .input_phys = ASUS_NB_WMI_FILE "/input0", 101 .input_phys = ASUS_NB_WMI_FILE "/input0",
102 .quirks = asus_nb_wmi_quirks,
84}; 103};
85 104
86 105
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 65b66aa44c78..95cba9ebf6c0 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -44,6 +44,7 @@
44#include <linux/debugfs.h> 44#include <linux/debugfs.h>
45#include <linux/seq_file.h> 45#include <linux/seq_file.h>
46#include <linux/platform_device.h> 46#include <linux/platform_device.h>
47#include <linux/thermal.h>
47#include <acpi/acpi_bus.h> 48#include <acpi/acpi_bus.h>
48#include <acpi/acpi_drivers.h> 49#include <acpi/acpi_drivers.h>
49 50
@@ -66,6 +67,8 @@ MODULE_LICENSE("GPL");
66#define NOTIFY_BRNUP_MAX 0x1f 67#define NOTIFY_BRNUP_MAX 0x1f
67#define NOTIFY_BRNDOWN_MIN 0x20 68#define NOTIFY_BRNDOWN_MIN 0x20
68#define NOTIFY_BRNDOWN_MAX 0x2e 69#define NOTIFY_BRNDOWN_MAX 0x2e
70#define NOTIFY_KBD_BRTUP 0xc4
71#define NOTIFY_KBD_BRTDWN 0xc5
69 72
70/* WMI Methods */ 73/* WMI Methods */
71#define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */ 74#define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */
@@ -93,6 +96,7 @@ MODULE_LICENSE("GPL");
93/* Wireless */ 96/* Wireless */
94#define ASUS_WMI_DEVID_HW_SWITCH 0x00010001 97#define ASUS_WMI_DEVID_HW_SWITCH 0x00010001
95#define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002 98#define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002
99#define ASUS_WMI_DEVID_CWAP 0x00010003
96#define ASUS_WMI_DEVID_WLAN 0x00010011 100#define ASUS_WMI_DEVID_WLAN 0x00010011
97#define ASUS_WMI_DEVID_BLUETOOTH 0x00010013 101#define ASUS_WMI_DEVID_BLUETOOTH 0x00010013
98#define ASUS_WMI_DEVID_GPS 0x00010015 102#define ASUS_WMI_DEVID_GPS 0x00010015
@@ -102,6 +106,12 @@ MODULE_LICENSE("GPL");
102 106
103/* Leds */ 107/* Leds */
104/* 0x000200XX and 0x000400XX */ 108/* 0x000200XX and 0x000400XX */
109#define ASUS_WMI_DEVID_LED1 0x00020011
110#define ASUS_WMI_DEVID_LED2 0x00020012
111#define ASUS_WMI_DEVID_LED3 0x00020013
112#define ASUS_WMI_DEVID_LED4 0x00020014
113#define ASUS_WMI_DEVID_LED5 0x00020015
114#define ASUS_WMI_DEVID_LED6 0x00020016
105 115
106/* Backlight and Brightness */ 116/* Backlight and Brightness */
107#define ASUS_WMI_DEVID_BACKLIGHT 0x00050011 117#define ASUS_WMI_DEVID_BACKLIGHT 0x00050011
@@ -174,13 +184,18 @@ struct asus_wmi {
174 184
175 struct led_classdev tpd_led; 185 struct led_classdev tpd_led;
176 int tpd_led_wk; 186 int tpd_led_wk;
187 struct led_classdev kbd_led;
188 int kbd_led_wk;
177 struct workqueue_struct *led_workqueue; 189 struct workqueue_struct *led_workqueue;
178 struct work_struct tpd_led_work; 190 struct work_struct tpd_led_work;
191 struct work_struct kbd_led_work;
179 192
180 struct asus_rfkill wlan; 193 struct asus_rfkill wlan;
181 struct asus_rfkill bluetooth; 194 struct asus_rfkill bluetooth;
182 struct asus_rfkill wimax; 195 struct asus_rfkill wimax;
183 struct asus_rfkill wwan3g; 196 struct asus_rfkill wwan3g;
197 struct asus_rfkill gps;
198 struct asus_rfkill uwb;
184 199
185 struct hotplug_slot *hotplug_slot; 200 struct hotplug_slot *hotplug_slot;
186 struct mutex hotplug_lock; 201 struct mutex hotplug_lock;
@@ -205,6 +220,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
205 asus->inputdev->phys = asus->driver->input_phys; 220 asus->inputdev->phys = asus->driver->input_phys;
206 asus->inputdev->id.bustype = BUS_HOST; 221 asus->inputdev->id.bustype = BUS_HOST;
207 asus->inputdev->dev.parent = &asus->platform_device->dev; 222 asus->inputdev->dev.parent = &asus->platform_device->dev;
223 set_bit(EV_REP, asus->inputdev->evbit);
208 224
209 err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL); 225 err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
210 if (err) 226 if (err)
@@ -359,30 +375,80 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
359 return read_tpd_led_state(asus); 375 return read_tpd_led_state(asus);
360} 376}
361 377
362static int asus_wmi_led_init(struct asus_wmi *asus) 378static void kbd_led_update(struct work_struct *work)
363{ 379{
364 int rv; 380 int ctrl_param = 0;
381 struct asus_wmi *asus;
365 382
366 if (read_tpd_led_state(asus) < 0) 383 asus = container_of(work, struct asus_wmi, kbd_led_work);
367 return 0;
368 384
369 asus->led_workqueue = create_singlethread_workqueue("led_workqueue"); 385 /*
370 if (!asus->led_workqueue) 386 * bits 0-2: level
371 return -ENOMEM; 387 * bit 7: light on/off
372 INIT_WORK(&asus->tpd_led_work, tpd_led_update); 388 */
389 if (asus->kbd_led_wk > 0)
390 ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
373 391
374 asus->tpd_led.name = "asus::touchpad"; 392 asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
375 asus->tpd_led.brightness_set = tpd_led_set; 393}
376 asus->tpd_led.brightness_get = tpd_led_get;
377 asus->tpd_led.max_brightness = 1;
378 394
379 rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led); 395static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
380 if (rv) { 396{
381 destroy_workqueue(asus->led_workqueue); 397 int retval;
382 return rv; 398
399 /*
400 * bits 0-2: level
401 * bit 7: light on/off
402 * bit 8-10: environment (0: dark, 1: normal, 2: light)
403 * bit 17: status unknown
404 */
405 retval = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_KBD_BACKLIGHT,
406 0xFFFF);
407
408 /* Unknown status is considered as off */
409 if (retval == 0x8000)
410 retval = 0;
411
412 if (retval >= 0) {
413 if (level)
414 *level = retval & 0x80 ? retval & 0x7F : 0;
415 if (env)
416 *env = (retval >> 8) & 0x7F;
417 retval = 0;
383 } 418 }
384 419
385 return 0; 420 return retval;
421}
422
423static void kbd_led_set(struct led_classdev *led_cdev,
424 enum led_brightness value)
425{
426 struct asus_wmi *asus;
427
428 asus = container_of(led_cdev, struct asus_wmi, kbd_led);
429
430 if (value > asus->kbd_led.max_brightness)
431 value = asus->kbd_led.max_brightness;
432 else if (value < 0)
433 value = 0;
434
435 asus->kbd_led_wk = value;
436 queue_work(asus->led_workqueue, &asus->kbd_led_work);
437}
438
439static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
440{
441 struct asus_wmi *asus;
442 int retval, value;
443
444 asus = container_of(led_cdev, struct asus_wmi, kbd_led);
445
446 retval = kbd_led_read(asus, &value, NULL);
447
448 if (retval < 0)
449 return retval;
450
451 return value;
386} 452}
387 453
388static void asus_wmi_led_exit(struct asus_wmi *asus) 454static void asus_wmi_led_exit(struct asus_wmi *asus)
@@ -393,6 +459,48 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
393 destroy_workqueue(asus->led_workqueue); 459 destroy_workqueue(asus->led_workqueue);
394} 460}
395 461
462static int asus_wmi_led_init(struct asus_wmi *asus)
463{
464 int rv = 0;
465
466 asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
467 if (!asus->led_workqueue)
468 return -ENOMEM;
469
470 if (read_tpd_led_state(asus) >= 0) {
471 INIT_WORK(&asus->tpd_led_work, tpd_led_update);
472
473 asus->tpd_led.name = "asus::touchpad";
474 asus->tpd_led.brightness_set = tpd_led_set;
475 asus->tpd_led.brightness_get = tpd_led_get;
476 asus->tpd_led.max_brightness = 1;
477
478 rv = led_classdev_register(&asus->platform_device->dev,
479 &asus->tpd_led);
480 if (rv)
481 goto error;
482 }
483
484 if (kbd_led_read(asus, NULL, NULL) >= 0) {
485 INIT_WORK(&asus->kbd_led_work, kbd_led_update);
486
487 asus->kbd_led.name = "asus::kbd_backlight";
488 asus->kbd_led.brightness_set = kbd_led_set;
489 asus->kbd_led.brightness_get = kbd_led_get;
490 asus->kbd_led.max_brightness = 3;
491
492 rv = led_classdev_register(&asus->platform_device->dev,
493 &asus->kbd_led);
494 }
495
496error:
497 if (rv)
498 asus_wmi_led_exit(asus);
499
500 return rv;
501}
502
503
396/* 504/*
397 * PCI hotplug (for wlan rfkill) 505 * PCI hotplug (for wlan rfkill)
398 */ 506 */
@@ -729,6 +837,16 @@ static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
729 rfkill_destroy(asus->wwan3g.rfkill); 837 rfkill_destroy(asus->wwan3g.rfkill);
730 asus->wwan3g.rfkill = NULL; 838 asus->wwan3g.rfkill = NULL;
731 } 839 }
840 if (asus->gps.rfkill) {
841 rfkill_unregister(asus->gps.rfkill);
842 rfkill_destroy(asus->gps.rfkill);
843 asus->gps.rfkill = NULL;
844 }
845 if (asus->uwb.rfkill) {
846 rfkill_unregister(asus->uwb.rfkill);
847 rfkill_destroy(asus->uwb.rfkill);
848 asus->uwb.rfkill = NULL;
849 }
732} 850}
733 851
734static int asus_wmi_rfkill_init(struct asus_wmi *asus) 852static int asus_wmi_rfkill_init(struct asus_wmi *asus)
@@ -763,6 +881,18 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
763 if (result && result != -ENODEV) 881 if (result && result != -ENODEV)
764 goto exit; 882 goto exit;
765 883
884 result = asus_new_rfkill(asus, &asus->gps, "asus-gps",
885 RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS);
886
887 if (result && result != -ENODEV)
888 goto exit;
889
890 result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb",
891 RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB);
892
893 if (result && result != -ENODEV)
894 goto exit;
895
766 if (!asus->driver->hotplug_wireless) 896 if (!asus->driver->hotplug_wireless)
767 goto exit; 897 goto exit;
768 898
@@ -797,8 +927,8 @@ exit:
797 * Hwmon device 927 * Hwmon device
798 */ 928 */
799static ssize_t asus_hwmon_pwm1(struct device *dev, 929static ssize_t asus_hwmon_pwm1(struct device *dev,
800 struct device_attribute *attr, 930 struct device_attribute *attr,
801 char *buf) 931 char *buf)
802{ 932{
803 struct asus_wmi *asus = dev_get_drvdata(dev); 933 struct asus_wmi *asus = dev_get_drvdata(dev);
804 u32 value; 934 u32 value;
@@ -809,7 +939,7 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
809 if (err < 0) 939 if (err < 0)
810 return err; 940 return err;
811 941
812 value |= 0xFF; 942 value &= 0xFF;
813 943
814 if (value == 1) /* Low Speed */ 944 if (value == 1) /* Low Speed */
815 value = 85; 945 value = 85;
@@ -825,7 +955,26 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
825 return sprintf(buf, "%d\n", value); 955 return sprintf(buf, "%d\n", value);
826} 956}
827 957
958static ssize_t asus_hwmon_temp1(struct device *dev,
959 struct device_attribute *attr,
960 char *buf)
961{
962 struct asus_wmi *asus = dev_get_drvdata(dev);
963 u32 value;
964 int err;
965
966 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);
967
968 if (err < 0)
969 return err;
970
971 value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
972
973 return sprintf(buf, "%d\n", value);
974}
975
828static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0); 976static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
977static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0);
829 978
830static ssize_t 979static ssize_t
831show_name(struct device *dev, struct device_attribute *attr, char *buf) 980show_name(struct device *dev, struct device_attribute *attr, char *buf)
@@ -836,12 +985,13 @@ static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
836 985
837static struct attribute *hwmon_attributes[] = { 986static struct attribute *hwmon_attributes[] = {
838 &sensor_dev_attr_pwm1.dev_attr.attr, 987 &sensor_dev_attr_pwm1.dev_attr.attr,
988 &sensor_dev_attr_temp1_input.dev_attr.attr,
839 &sensor_dev_attr_name.dev_attr.attr, 989 &sensor_dev_attr_name.dev_attr.attr,
840 NULL 990 NULL
841}; 991};
842 992
843static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, 993static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
844 struct attribute *attr, int idx) 994 struct attribute *attr, int idx)
845{ 995{
846 struct device *dev = container_of(kobj, struct device, kobj); 996 struct device *dev = container_of(kobj, struct device, kobj);
847 struct platform_device *pdev = to_platform_device(dev->parent); 997 struct platform_device *pdev = to_platform_device(dev->parent);
@@ -852,6 +1002,8 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
852 1002
853 if (attr == &sensor_dev_attr_pwm1.dev_attr.attr) 1003 if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
854 dev_id = ASUS_WMI_DEVID_FAN_CTRL; 1004 dev_id = ASUS_WMI_DEVID_FAN_CTRL;
1005 else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr)
1006 dev_id = ASUS_WMI_DEVID_THERMAL_CTRL;
855 1007
856 if (dev_id != -1) { 1008 if (dev_id != -1) {
857 int err = asus_wmi_get_devstate(asus, dev_id, &value); 1009 int err = asus_wmi_get_devstate(asus, dev_id, &value);
@@ -869,9 +1021,13 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
869 * - reverved bits are non-zero 1021 * - reverved bits are non-zero
870 * - sfun and presence bit are not set 1022 * - sfun and presence bit are not set
871 */ 1023 */
872 if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000 1024 if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
873 || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT))) 1025 || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
874 ok = false; 1026 ok = false;
1027 } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) {
1028 /* If value is zero, something is clearly wrong */
1029 if (value == 0)
1030 ok = false;
875 } 1031 }
876 1032
877 return ok ? attr->mode : 0; 1033 return ok ? attr->mode : 0;
@@ -904,6 +1060,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
904 pr_err("Could not register asus hwmon device\n"); 1060 pr_err("Could not register asus hwmon device\n");
905 return PTR_ERR(hwmon); 1061 return PTR_ERR(hwmon);
906 } 1062 }
1063 dev_set_drvdata(hwmon, asus);
907 asus->hwmon_device = hwmon; 1064 asus->hwmon_device = hwmon;
908 result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group); 1065 result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
909 if (result) 1066 if (result)
@@ -1060,6 +1217,8 @@ static void asus_wmi_notify(u32 value, void *context)
1060 acpi_status status; 1217 acpi_status status;
1061 int code; 1218 int code;
1062 int orig_code; 1219 int orig_code;
1220 unsigned int key_value = 1;
1221 bool autorelease = 1;
1063 1222
1064 status = wmi_get_event_data(value, &response); 1223 status = wmi_get_event_data(value, &response);
1065 if (status != AE_OK) { 1224 if (status != AE_OK) {
@@ -1075,6 +1234,13 @@ static void asus_wmi_notify(u32 value, void *context)
1075 code = obj->integer.value; 1234 code = obj->integer.value;
1076 orig_code = code; 1235 orig_code = code;
1077 1236
1237 if (asus->driver->key_filter) {
1238 asus->driver->key_filter(asus->driver, &code, &key_value,
1239 &autorelease);
1240 if (code == ASUS_WMI_KEY_IGNORE)
1241 goto exit;
1242 }
1243
1078 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX) 1244 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
1079 code = NOTIFY_BRNUP_MIN; 1245 code = NOTIFY_BRNUP_MIN;
1080 else if (code >= NOTIFY_BRNDOWN_MIN && 1246 else if (code >= NOTIFY_BRNDOWN_MIN &&
@@ -1084,7 +1250,8 @@ static void asus_wmi_notify(u32 value, void *context)
1084 if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) { 1250 if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
1085 if (!acpi_video_backlight_support()) 1251 if (!acpi_video_backlight_support())
1086 asus_wmi_backlight_notify(asus, orig_code); 1252 asus_wmi_backlight_notify(asus, orig_code);
1087 } else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true)) 1253 } else if (!sparse_keymap_report_event(asus->inputdev, code,
1254 key_value, autorelease))
1088 pr_info("Unknown key %x pressed\n", code); 1255 pr_info("Unknown key %x pressed\n", code);
1089 1256
1090exit: 1257exit:
@@ -1164,14 +1331,18 @@ ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
1164static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr, 1331static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
1165 const char *buf, size_t count) 1332 const char *buf, size_t count)
1166{ 1333{
1167 int value; 1334 int value, rv;
1168 1335
1169 if (!count || sscanf(buf, "%i", &value) != 1) 1336 if (!count || sscanf(buf, "%i", &value) != 1)
1170 return -EINVAL; 1337 return -EINVAL;
1171 if (value < 0 || value > 2) 1338 if (value < 0 || value > 2)
1172 return -EINVAL; 1339 return -EINVAL;
1173 1340
1174 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL); 1341 rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
1342 if (rv < 0)
1343 return rv;
1344
1345 return count;
1175} 1346}
1176 1347
1177static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv); 1348static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
@@ -1234,7 +1405,7 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
1234 1405
1235 /* We don't know yet what to do with this version... */ 1406 /* We don't know yet what to do with this version... */
1236 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) { 1407 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
1237 pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF); 1408 pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF);
1238 asus->spec = rv; 1409 asus->spec = rv;
1239 } 1410 }
1240 1411
@@ -1266,6 +1437,12 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
1266 return -ENODEV; 1437 return -ENODEV;
1267 } 1438 }
1268 1439
1440 /* CWAP allow to define the behavior of the Fn+F2 key,
1441 * this method doesn't seems to be present on Eee PCs */
1442 if (asus->driver->wapf >= 0)
1443 asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
1444 asus->driver->wapf, NULL);
1445
1269 return asus_wmi_sysfs_init(asus->platform_device); 1446 return asus_wmi_sysfs_init(asus->platform_device);
1270} 1447}
1271 1448
@@ -1568,6 +1745,14 @@ static int asus_hotk_restore(struct device *device)
1568 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G); 1745 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
1569 rfkill_set_sw_state(asus->wwan3g.rfkill, bl); 1746 rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
1570 } 1747 }
1748 if (asus->gps.rfkill) {
1749 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS);
1750 rfkill_set_sw_state(asus->gps.rfkill, bl);
1751 }
1752 if (asus->uwb.rfkill) {
1753 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);
1754 rfkill_set_sw_state(asus->uwb.rfkill, bl);
1755 }
1571 1756
1572 return 0; 1757 return 0;
1573} 1758}
@@ -1604,7 +1789,7 @@ static int asus_wmi_probe(struct platform_device *pdev)
1604 1789
1605static bool used; 1790static bool used;
1606 1791
1607int asus_wmi_register_driver(struct asus_wmi_driver *driver) 1792int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver)
1608{ 1793{
1609 struct platform_driver *platform_driver; 1794 struct platform_driver *platform_driver;
1610 struct platform_device *platform_device; 1795 struct platform_device *platform_device;
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
index c044522c8766..8147c10161cc 100644
--- a/drivers/platform/x86/asus-wmi.h
+++ b/drivers/platform/x86/asus-wmi.h
@@ -29,12 +29,15 @@
29 29
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31 31
32#define ASUS_WMI_KEY_IGNORE (-1)
33
32struct module; 34struct module;
33struct key_entry; 35struct key_entry;
34struct asus_wmi; 36struct asus_wmi;
35 37
36struct asus_wmi_driver { 38struct asus_wmi_driver {
37 bool hotplug_wireless; 39 bool hotplug_wireless;
40 int wapf;
38 41
39 const char *name; 42 const char *name;
40 struct module *owner; 43 struct module *owner;
@@ -44,6 +47,10 @@ struct asus_wmi_driver {
44 const struct key_entry *keymap; 47 const struct key_entry *keymap;
45 const char *input_name; 48 const char *input_name;
46 const char *input_phys; 49 const char *input_phys;
50 /* Returns new code, value, and autorelease values in arguments.
51 * Return ASUS_WMI_KEY_IGNORE in code if event should be ignored. */
52 void (*key_filter) (struct asus_wmi_driver *driver, int *code,
53 unsigned int *value, bool *autorelease);
47 54
48 int (*probe) (struct platform_device *device); 55 int (*probe) (struct platform_device *device);
49 void (*quirks) (struct asus_wmi_driver *driver); 56 void (*quirks) (struct asus_wmi_driver *driver);
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index e39ab1d3ed87..f31fa4efa725 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -612,7 +612,6 @@ static int __init dell_init(void)
612 if (!bufferpage) 612 if (!bufferpage)
613 goto fail_buffer; 613 goto fail_buffer;
614 buffer = page_address(bufferpage); 614 buffer = page_address(bufferpage);
615 mutex_init(&buffer_mutex);
616 615
617 ret = dell_setup_rfkill(); 616 ret = dell_setup_rfkill();
618 617
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index ce790827e199..fa9a2171cc13 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -54,6 +54,8 @@ MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
54 */ 54 */
55 55
56static const struct key_entry dell_wmi_legacy_keymap[] __initconst = { 56static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
57 { KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
58
57 { KE_KEY, 0xe045, { KEY_PROG1 } }, 59 { KE_KEY, 0xe045, { KEY_PROG1 } },
58 { KE_KEY, 0xe009, { KEY_EJECTCD } }, 60 { KE_KEY, 0xe009, { KEY_EJECTCD } },
59 61
@@ -85,6 +87,11 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
85 { KE_IGNORE, 0xe013, { KEY_RESERVED } }, 87 { KE_IGNORE, 0xe013, { KEY_RESERVED } },
86 88
87 { KE_IGNORE, 0xe020, { KEY_MUTE } }, 89 { KE_IGNORE, 0xe020, { KEY_MUTE } },
90
91 /* Shortcut and audio panel keys */
92 { KE_IGNORE, 0xe025, { KEY_RESERVED } },
93 { KE_IGNORE, 0xe026, { KEY_RESERVED } },
94
88 { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } }, 95 { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
89 { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } }, 96 { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
90 { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } }, 97 { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
@@ -92,6 +99,9 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
92 { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } }, 99 { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
93 { KE_IGNORE, 0xe045, { KEY_NUMLOCK } }, 100 { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
94 { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } }, 101 { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
102 { KE_IGNORE, 0xe0f7, { KEY_MUTE } },
103 { KE_IGNORE, 0xe0f8, { KEY_VOLUMEDOWN } },
104 { KE_IGNORE, 0xe0f9, { KEY_VOLUMEUP } },
95 { KE_END, 0 } 105 { KE_END, 0 }
96}; 106};
97 107
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 4aa867a9b88b..9f6e64302b45 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -56,6 +56,11 @@ MODULE_PARM_DESC(hotplug_wireless,
56 "If your laptop needs that, please report to " 56 "If your laptop needs that, please report to "
57 "acpi4asus-user@lists.sourceforge.net."); 57 "acpi4asus-user@lists.sourceforge.net.");
58 58
59/* Values for T101MT "Home" key */
60#define HOME_PRESS 0xe4
61#define HOME_HOLD 0xea
62#define HOME_RELEASE 0xe5
63
59static const struct key_entry eeepc_wmi_keymap[] = { 64static const struct key_entry eeepc_wmi_keymap[] = {
60 /* Sleep already handled via generic ACPI code */ 65 /* Sleep already handled via generic ACPI code */
61 { KE_KEY, 0x30, { KEY_VOLUMEUP } }, 66 { KE_KEY, 0x30, { KEY_VOLUMEUP } },
@@ -71,6 +76,7 @@ static const struct key_entry eeepc_wmi_keymap[] = {
71 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } }, 76 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
72 { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */ 77 { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
73 { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */ 78 { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
79 { KE_KEY, HOME_PRESS, { KEY_CONFIG } }, /* Home/Express gate key */
74 { KE_KEY, 0xe8, { KEY_SCREENLOCK } }, 80 { KE_KEY, 0xe8, { KEY_SCREENLOCK } },
75 { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } }, 81 { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
76 { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } }, 82 { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
@@ -81,6 +87,25 @@ static const struct key_entry eeepc_wmi_keymap[] = {
81 { KE_END, 0}, 87 { KE_END, 0},
82}; 88};
83 89
90static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
91 unsigned int *value, bool *autorelease)
92{
93 switch (*code) {
94 case HOME_PRESS:
95 *value = 1;
96 *autorelease = 0;
97 break;
98 case HOME_HOLD:
99 *code = ASUS_WMI_KEY_IGNORE;
100 break;
101 case HOME_RELEASE:
102 *code = HOME_PRESS;
103 *value = 0;
104 *autorelease = 0;
105 break;
106 }
107}
108
84static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level, 109static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
85 void *context, void **retval) 110 void *context, void **retval)
86{ 111{
@@ -141,6 +166,7 @@ static void eeepc_dmi_check(struct asus_wmi_driver *driver)
141static void eeepc_wmi_quirks(struct asus_wmi_driver *driver) 166static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
142{ 167{
143 driver->hotplug_wireless = hotplug_wireless; 168 driver->hotplug_wireless = hotplug_wireless;
169 driver->wapf = -1;
144 eeepc_dmi_check(driver); 170 eeepc_dmi_check(driver);
145} 171}
146 172
@@ -151,6 +177,7 @@ static struct asus_wmi_driver asus_wmi_driver = {
151 .keymap = eeepc_wmi_keymap, 177 .keymap = eeepc_wmi_keymap,
152 .input_name = "Eee PC WMI hotkeys", 178 .input_name = "Eee PC WMI hotkeys",
153 .input_phys = EEEPC_WMI_FILE "/input0", 179 .input_phys = EEEPC_WMI_FILE "/input0",
180 .key_filter = eeepc_wmi_key_filter,
154 .probe = eeepc_wmi_probe, 181 .probe = eeepc_wmi_probe,
155 .quirks = eeepc_wmi_quirks, 182 .quirks = eeepc_wmi_quirks,
156}; 183};
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index bfdda33feb26..0c595410e788 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -32,13 +32,22 @@
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/input.h> 33#include <linux/input.h>
34#include <linux/input/sparse-keymap.h> 34#include <linux/input/sparse-keymap.h>
35#include <linux/backlight.h>
36#include <linux/fb.h>
35 37
36#define IDEAPAD_RFKILL_DEV_NUM (3) 38#define IDEAPAD_RFKILL_DEV_NUM (3)
37 39
40#define CFG_BT_BIT (16)
41#define CFG_3G_BIT (17)
42#define CFG_WIFI_BIT (18)
43#define CFG_CAMERA_BIT (19)
44
38struct ideapad_private { 45struct ideapad_private {
39 struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; 46 struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
40 struct platform_device *platform_device; 47 struct platform_device *platform_device;
41 struct input_dev *inputdev; 48 struct input_dev *inputdev;
49 struct backlight_device *blightdev;
50 unsigned long cfg;
42}; 51};
43 52
44static acpi_handle ideapad_handle; 53static acpi_handle ideapad_handle;
@@ -155,7 +164,7 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
155} 164}
156 165
157/* 166/*
158 * camera power 167 * sysfs
159 */ 168 */
160static ssize_t show_ideapad_cam(struct device *dev, 169static ssize_t show_ideapad_cam(struct device *dev,
161 struct device_attribute *attr, 170 struct device_attribute *attr,
@@ -186,6 +195,44 @@ static ssize_t store_ideapad_cam(struct device *dev,
186 195
187static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); 196static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
188 197
198static ssize_t show_ideapad_cfg(struct device *dev,
199 struct device_attribute *attr,
200 char *buf)
201{
202 struct ideapad_private *priv = dev_get_drvdata(dev);
203
204 return sprintf(buf, "0x%.8lX\n", priv->cfg);
205}
206
207static DEVICE_ATTR(cfg, 0444, show_ideapad_cfg, NULL);
208
209static struct attribute *ideapad_attributes[] = {
210 &dev_attr_camera_power.attr,
211 &dev_attr_cfg.attr,
212 NULL
213};
214
215static mode_t ideapad_is_visible(struct kobject *kobj,
216 struct attribute *attr,
217 int idx)
218{
219 struct device *dev = container_of(kobj, struct device, kobj);
220 struct ideapad_private *priv = dev_get_drvdata(dev);
221 bool supported;
222
223 if (attr == &dev_attr_camera_power.attr)
224 supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
225 else
226 supported = true;
227
228 return supported ? attr->mode : 0;
229}
230
231static struct attribute_group ideapad_attribute_group = {
232 .is_visible = ideapad_is_visible,
233 .attrs = ideapad_attributes
234};
235
189/* 236/*
190 * Rfkill 237 * Rfkill
191 */ 238 */
@@ -197,9 +244,9 @@ struct ideapad_rfk_data {
197}; 244};
198 245
199const struct ideapad_rfk_data ideapad_rfk_data[] = { 246const struct ideapad_rfk_data ideapad_rfk_data[] = {
200 { "ideapad_wlan", 18, 0x15, RFKILL_TYPE_WLAN }, 247 { "ideapad_wlan", CFG_WIFI_BIT, 0x15, RFKILL_TYPE_WLAN },
201 { "ideapad_bluetooth", 16, 0x17, RFKILL_TYPE_BLUETOOTH }, 248 { "ideapad_bluetooth", CFG_BT_BIT, 0x17, RFKILL_TYPE_BLUETOOTH },
202 { "ideapad_3g", 17, 0x20, RFKILL_TYPE_WWAN }, 249 { "ideapad_3g", CFG_3G_BIT, 0x20, RFKILL_TYPE_WWAN },
203}; 250};
204 251
205static int ideapad_rfk_set(void *data, bool blocked) 252static int ideapad_rfk_set(void *data, bool blocked)
@@ -265,8 +312,7 @@ static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
265 return 0; 312 return 0;
266} 313}
267 314
268static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice, 315static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
269 int dev)
270{ 316{
271 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); 317 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
272 318
@@ -280,15 +326,6 @@ static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
280/* 326/*
281 * Platform device 327 * Platform device
282 */ 328 */
283static struct attribute *ideapad_attributes[] = {
284 &dev_attr_camera_power.attr,
285 NULL
286};
287
288static struct attribute_group ideapad_attribute_group = {
289 .attrs = ideapad_attributes
290};
291
292static int __devinit ideapad_platform_init(struct ideapad_private *priv) 329static int __devinit ideapad_platform_init(struct ideapad_private *priv)
293{ 330{
294 int result; 331 int result;
@@ -369,7 +406,7 @@ err_free_dev:
369 return error; 406 return error;
370} 407}
371 408
372static void __devexit ideapad_input_exit(struct ideapad_private *priv) 409static void ideapad_input_exit(struct ideapad_private *priv)
373{ 410{
374 sparse_keymap_free(priv->inputdev); 411 sparse_keymap_free(priv->inputdev);
375 input_unregister_device(priv->inputdev); 412 input_unregister_device(priv->inputdev);
@@ -383,6 +420,98 @@ static void ideapad_input_report(struct ideapad_private *priv,
383} 420}
384 421
385/* 422/*
423 * backlight
424 */
425static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
426{
427 unsigned long now;
428
429 if (read_ec_data(ideapad_handle, 0x12, &now))
430 return -EIO;
431 return now;
432}
433
434static int ideapad_backlight_update_status(struct backlight_device *blightdev)
435{
436 if (write_ec_cmd(ideapad_handle, 0x13, blightdev->props.brightness))
437 return -EIO;
438 if (write_ec_cmd(ideapad_handle, 0x33,
439 blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
440 return -EIO;
441
442 return 0;
443}
444
445static const struct backlight_ops ideapad_backlight_ops = {
446 .get_brightness = ideapad_backlight_get_brightness,
447 .update_status = ideapad_backlight_update_status,
448};
449
450static int ideapad_backlight_init(struct ideapad_private *priv)
451{
452 struct backlight_device *blightdev;
453 struct backlight_properties props;
454 unsigned long max, now, power;
455
456 if (read_ec_data(ideapad_handle, 0x11, &max))
457 return -EIO;
458 if (read_ec_data(ideapad_handle, 0x12, &now))
459 return -EIO;
460 if (read_ec_data(ideapad_handle, 0x18, &power))
461 return -EIO;
462
463 memset(&props, 0, sizeof(struct backlight_properties));
464 props.max_brightness = max;
465 props.type = BACKLIGHT_PLATFORM;
466 blightdev = backlight_device_register("ideapad",
467 &priv->platform_device->dev,
468 priv,
469 &ideapad_backlight_ops,
470 &props);
471 if (IS_ERR(blightdev)) {
472 pr_err("Could not register backlight device\n");
473 return PTR_ERR(blightdev);
474 }
475
476 priv->blightdev = blightdev;
477 blightdev->props.brightness = now;
478 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
479 backlight_update_status(blightdev);
480
481 return 0;
482}
483
484static void ideapad_backlight_exit(struct ideapad_private *priv)
485{
486 if (priv->blightdev)
487 backlight_device_unregister(priv->blightdev);
488 priv->blightdev = NULL;
489}
490
491static void ideapad_backlight_notify_power(struct ideapad_private *priv)
492{
493 unsigned long power;
494 struct backlight_device *blightdev = priv->blightdev;
495
496 if (read_ec_data(ideapad_handle, 0x18, &power))
497 return;
498 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
499}
500
501static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
502{
503 unsigned long now;
504
505 /* if we control brightness via acpi video driver */
506 if (priv->blightdev == NULL) {
507 read_ec_data(ideapad_handle, 0x12, &now);
508 return;
509 }
510
511 backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
512}
513
514/*
386 * module init/exit 515 * module init/exit
387 */ 516 */
388static const struct acpi_device_id ideapad_device_ids[] = { 517static const struct acpi_device_id ideapad_device_ids[] = {
@@ -393,10 +522,11 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
393 522
394static int __devinit ideapad_acpi_add(struct acpi_device *adevice) 523static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
395{ 524{
396 int ret, i, cfg; 525 int ret, i;
526 unsigned long cfg;
397 struct ideapad_private *priv; 527 struct ideapad_private *priv;
398 528
399 if (read_method_int(adevice->handle, "_CFG", &cfg)) 529 if (read_method_int(adevice->handle, "_CFG", (int *)&cfg))
400 return -ENODEV; 530 return -ENODEV;
401 531
402 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 532 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -404,6 +534,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
404 return -ENOMEM; 534 return -ENOMEM;
405 dev_set_drvdata(&adevice->dev, priv); 535 dev_set_drvdata(&adevice->dev, priv);
406 ideapad_handle = adevice->handle; 536 ideapad_handle = adevice->handle;
537 priv->cfg = cfg;
407 538
408 ret = ideapad_platform_init(priv); 539 ret = ideapad_platform_init(priv);
409 if (ret) 540 if (ret)
@@ -414,15 +545,25 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
414 goto input_failed; 545 goto input_failed;
415 546
416 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) { 547 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
417 if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg)) 548 if (test_bit(ideapad_rfk_data[i].cfgbit, &cfg))
418 ideapad_register_rfkill(adevice, i); 549 ideapad_register_rfkill(adevice, i);
419 else 550 else
420 priv->rfk[i] = NULL; 551 priv->rfk[i] = NULL;
421 } 552 }
422 ideapad_sync_rfk_state(adevice); 553 ideapad_sync_rfk_state(adevice);
423 554
555 if (!acpi_video_backlight_support()) {
556 ret = ideapad_backlight_init(priv);
557 if (ret && ret != -ENODEV)
558 goto backlight_failed;
559 }
560
424 return 0; 561 return 0;
425 562
563backlight_failed:
564 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
565 ideapad_unregister_rfkill(adevice, i);
566 ideapad_input_exit(priv);
426input_failed: 567input_failed:
427 ideapad_platform_exit(priv); 568 ideapad_platform_exit(priv);
428platform_failed: 569platform_failed:
@@ -435,6 +576,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
435 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); 576 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
436 int i; 577 int i;
437 578
579 ideapad_backlight_exit(priv);
438 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 580 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
439 ideapad_unregister_rfkill(adevice, i); 581 ideapad_unregister_rfkill(adevice, i);
440 ideapad_input_exit(priv); 582 ideapad_input_exit(priv);
@@ -459,12 +601,19 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
459 vpc1 = (vpc2 << 8) | vpc1; 601 vpc1 = (vpc2 << 8) | vpc1;
460 for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) { 602 for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
461 if (test_bit(vpc_bit, &vpc1)) { 603 if (test_bit(vpc_bit, &vpc1)) {
462 if (vpc_bit == 9) 604 switch (vpc_bit) {
605 case 9:
463 ideapad_sync_rfk_state(adevice); 606 ideapad_sync_rfk_state(adevice);
464 else if (vpc_bit == 4) 607 break;
465 read_ec_data(handle, 0x12, &vpc2); 608 case 4:
466 else 609 ideapad_backlight_notify_brightness(priv);
610 break;
611 case 2:
612 ideapad_backlight_notify_power(priv);
613 break;
614 default:
467 ideapad_input_report(priv, vpc_bit); 615 ideapad_input_report(priv, vpc_bit);
616 }
468 } 617 }
469 } 618 }
470} 619}
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index 5ffe7c398148..809a3ae943c6 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -403,7 +403,7 @@ static void ips_cpu_raise(struct ips_driver *ips)
403 403
404 thm_writew(THM_MPCPC, (new_tdp_limit * 10) / 8); 404 thm_writew(THM_MPCPC, (new_tdp_limit * 10) / 8);
405 405
406 turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN; 406 turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
407 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 407 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
408 408
409 turbo_override &= ~TURBO_TDP_MASK; 409 turbo_override &= ~TURBO_TDP_MASK;
@@ -438,7 +438,7 @@ static void ips_cpu_lower(struct ips_driver *ips)
438 438
439 thm_writew(THM_MPCPC, (new_limit * 10) / 8); 439 thm_writew(THM_MPCPC, (new_limit * 10) / 8);
440 440
441 turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN; 441 turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
442 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 442 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
443 443
444 turbo_override &= ~TURBO_TDP_MASK; 444 turbo_override &= ~TURBO_TDP_MASK;
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index 809adea4965f..abddc83e9fd7 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -477,6 +477,8 @@ static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
477 return AE_ERROR; 477 return AE_ERROR;
478 } 478 }
479 479
480 return AE_OK;
481
480 aux1_not_found: 482 aux1_not_found:
481 if (status == AE_NOT_FOUND) 483 if (status == AE_NOT_FOUND)
482 return AE_OK; 484 return AE_OK;
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index 3a578323122b..ccd7b1f83519 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -493,20 +493,30 @@ static int mid_thermal_probe(struct platform_device *pdev)
493 493
494 /* Register each sensor with the generic thermal framework*/ 494 /* Register each sensor with the generic thermal framework*/
495 for (i = 0; i < MSIC_THERMAL_SENSORS; i++) { 495 for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
496 struct thermal_device_info *td_info = initialize_sensor(i);
497
498 if (!td_info) {
499 ret = -ENOMEM;
500 goto err;
501 }
496 pinfo->tzd[i] = thermal_zone_device_register(name[i], 502 pinfo->tzd[i] = thermal_zone_device_register(name[i],
497 0, initialize_sensor(i), &tzd_ops, 0, 0, 0, 0); 503 0, td_info, &tzd_ops, 0, 0, 0, 0);
498 if (IS_ERR(pinfo->tzd[i])) 504 if (IS_ERR(pinfo->tzd[i])) {
499 goto reg_fail; 505 kfree(td_info);
506 ret = PTR_ERR(pinfo->tzd[i]);
507 goto err;
508 }
500 } 509 }
501 510
502 pinfo->pdev = pdev; 511 pinfo->pdev = pdev;
503 platform_set_drvdata(pdev, pinfo); 512 platform_set_drvdata(pdev, pinfo);
504 return 0; 513 return 0;
505 514
506reg_fail: 515err:
507 ret = PTR_ERR(pinfo->tzd[i]); 516 while (--i >= 0) {
508 while (--i >= 0) 517 kfree(pinfo->tzd[i]->devdata);
509 thermal_zone_device_unregister(pinfo->tzd[i]); 518 thermal_zone_device_unregister(pinfo->tzd[i]);
519 }
510 configure_adc(0); 520 configure_adc(0);
511 kfree(pinfo); 521 kfree(pinfo);
512 return ret; 522 return ret;
@@ -524,8 +534,10 @@ static int mid_thermal_remove(struct platform_device *pdev)
524 int i; 534 int i;
525 struct platform_info *pinfo = platform_get_drvdata(pdev); 535 struct platform_info *pinfo = platform_get_drvdata(pdev);
526 536
527 for (i = 0; i < MSIC_THERMAL_SENSORS; i++) 537 for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
538 kfree(pinfo->tzd[i]->devdata);
528 thermal_zone_device_unregister(pinfo->tzd[i]); 539 thermal_zone_device_unregister(pinfo->tzd[i]);
540 }
529 541
530 kfree(pinfo); 542 kfree(pinfo);
531 platform_set_drvdata(pdev, NULL); 543 platform_set_drvdata(pdev, NULL);
diff --git a/drivers/platform/x86/intel_rar_register.c b/drivers/platform/x86/intel_rar_register.c
index bde47e9080cd..c8a6aed45277 100644
--- a/drivers/platform/x86/intel_rar_register.c
+++ b/drivers/platform/x86/intel_rar_register.c
@@ -637,15 +637,13 @@ end_function:
637 return error; 637 return error;
638} 638}
639 639
640const struct pci_device_id rar_pci_id_tbl[] = { 640static DEFINE_PCI_DEVICE_TABLE(rar_pci_id_tbl) = {
641 { PCI_VDEVICE(INTEL, 0x4110) }, 641 { PCI_VDEVICE(INTEL, 0x4110) },
642 { 0 } 642 { 0 }
643}; 643};
644 644
645MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl); 645MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
646 646
647const struct pci_device_id *my_id_table = rar_pci_id_tbl;
648
649/* field for registering driver to PCI device */ 647/* field for registering driver to PCI device */
650static struct pci_driver rar_pci_driver = { 648static struct pci_driver rar_pci_driver = {
651 .name = "rar_register_driver", 649 .name = "rar_register_driver",
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 940accbe28d3..c86665369a22 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -725,7 +725,7 @@ static void ipc_remove(struct pci_dev *pdev)
725 intel_scu_devices_destroy(); 725 intel_scu_devices_destroy();
726} 726}
727 727
728static const struct pci_device_id pci_ids[] = { 728static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
729 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)}, 729 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)},
730 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)}, 730 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)},
731 { 0,} 731 { 0,}
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 3ff629df9f01..f204643c5052 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -538,6 +538,15 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
538 }, 538 },
539 .callback = dmi_check_cb 539 .callback = dmi_check_cb
540 }, 540 },
541 {
542 .ident = "MSI U270",
543 .matches = {
544 DMI_MATCH(DMI_SYS_VENDOR,
545 "Micro-Star International Co., Ltd."),
546 DMI_MATCH(DMI_PRODUCT_NAME, "U270 series"),
547 },
548 .callback = dmi_check_cb
549 },
541 { } 550 { }
542}; 551};
543 552
@@ -996,3 +1005,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*");
996MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N051:*"); 1005MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N051:*");
997MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*"); 1006MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*");
998MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*"); 1007MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*");
1008MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnU270series:*");
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index c832e3356cd6..6f40bf202dc7 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -272,6 +272,7 @@ static int __init msi_wmi_init(void)
272err_free_backlight: 272err_free_backlight:
273 backlight_device_unregister(backlight); 273 backlight_device_unregister(backlight);
274err_free_input: 274err_free_input:
275 sparse_keymap_free(msi_wmi_input_dev);
275 input_unregister_device(msi_wmi_input_dev); 276 input_unregister_device(msi_wmi_input_dev);
276err_uninstall_notifier: 277err_uninstall_notifier:
277 wmi_remove_notify_handler(MSIWMI_EVENT_GUID); 278 wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index d347116d150e..359163011044 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -521,6 +521,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
521 .callback = dmi_check_cb, 521 .callback = dmi_check_cb,
522 }, 522 },
523 { 523 {
524 .ident = "N510",
525 .matches = {
526 DMI_MATCH(DMI_SYS_VENDOR,
527 "SAMSUNG ELECTRONICS CO., LTD."),
528 DMI_MATCH(DMI_PRODUCT_NAME, "N510"),
529 DMI_MATCH(DMI_BOARD_NAME, "N510"),
530 },
531 .callback = dmi_check_cb,
532 },
533 {
524 .ident = "X125", 534 .ident = "X125",
525 .matches = { 535 .matches = {
526 DMI_MATCH(DMI_SYS_VENDOR, 536 DMI_MATCH(DMI_SYS_VENDOR,
@@ -601,6 +611,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
601 .callback = dmi_check_cb, 611 .callback = dmi_check_cb,
602 }, 612 },
603 { 613 {
614 .ident = "N150/N210/N220",
615 .matches = {
616 DMI_MATCH(DMI_SYS_VENDOR,
617 "SAMSUNG ELECTRONICS CO., LTD."),
618 DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
619 DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
620 },
621 .callback = dmi_check_cb,
622 },
623 {
604 .ident = "N150/N210/N220/N230", 624 .ident = "N150/N210/N220/N230",
605 .matches = { 625 .matches = {
606 DMI_MATCH(DMI_SYS_VENDOR, 626 DMI_MATCH(DMI_SYS_VENDOR,
diff --git a/drivers/platform/x86/samsung-q10.c b/drivers/platform/x86/samsung-q10.c
new file mode 100644
index 000000000000..1e54ae74274c
--- /dev/null
+++ b/drivers/platform/x86/samsung-q10.c
@@ -0,0 +1,196 @@
1/*
2 * Driver for Samsung Q10 and related laptops: controls the backlight
3 *
4 * Copyright (c) 2011 Frederick van der Wyck <fvanderwyck@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/backlight.h>
17#include <linux/i8042.h>
18#include <linux/dmi.h>
19
20#define SAMSUNGQ10_BL_MAX_INTENSITY 255
21#define SAMSUNGQ10_BL_DEFAULT_INTENSITY 185
22
23#define SAMSUNGQ10_BL_8042_CMD 0xbe
24#define SAMSUNGQ10_BL_8042_DATA { 0x89, 0x91 }
25
26static int samsungq10_bl_brightness;
27
28static bool force;
29module_param(force, bool, 0);
30MODULE_PARM_DESC(force,
31 "Disable the DMI check and force the driver to be loaded");
32
33static int samsungq10_bl_set_intensity(struct backlight_device *bd)
34{
35
36 int brightness = bd->props.brightness;
37 unsigned char c[3] = SAMSUNGQ10_BL_8042_DATA;
38
39 c[2] = (unsigned char)brightness;
40 i8042_lock_chip();
41 i8042_command(c, (0x30 << 8) | SAMSUNGQ10_BL_8042_CMD);
42 i8042_unlock_chip();
43 samsungq10_bl_brightness = brightness;
44
45 return 0;
46}
47
48static int samsungq10_bl_get_intensity(struct backlight_device *bd)
49{
50 return samsungq10_bl_brightness;
51}
52
53static const struct backlight_ops samsungq10_bl_ops = {
54 .get_brightness = samsungq10_bl_get_intensity,
55 .update_status = samsungq10_bl_set_intensity,
56};
57
58#ifdef CONFIG_PM_SLEEP
59static int samsungq10_suspend(struct device *dev)
60{
61 return 0;
62}
63
64static int samsungq10_resume(struct device *dev)
65{
66
67 struct backlight_device *bd = dev_get_drvdata(dev);
68
69 samsungq10_bl_set_intensity(bd);
70 return 0;
71}
72#else
73#define samsungq10_suspend NULL
74#define samsungq10_resume NULL
75#endif
76
77static SIMPLE_DEV_PM_OPS(samsungq10_pm_ops,
78 samsungq10_suspend, samsungq10_resume);
79
80static int __devinit samsungq10_probe(struct platform_device *pdev)
81{
82
83 struct backlight_properties props;
84 struct backlight_device *bd;
85
86 memset(&props, 0, sizeof(struct backlight_properties));
87 props.type = BACKLIGHT_PLATFORM;
88 props.max_brightness = SAMSUNGQ10_BL_MAX_INTENSITY;
89 bd = backlight_device_register("samsung", &pdev->dev, NULL,
90 &samsungq10_bl_ops, &props);
91 if (IS_ERR(bd))
92 return PTR_ERR(bd);
93
94 platform_set_drvdata(pdev, bd);
95
96 bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
97 samsungq10_bl_set_intensity(bd);
98
99 return 0;
100}
101
102static int __devexit samsungq10_remove(struct platform_device *pdev)
103{
104
105 struct backlight_device *bd = platform_get_drvdata(pdev);
106
107 bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
108 samsungq10_bl_set_intensity(bd);
109
110 backlight_device_unregister(bd);
111
112 return 0;
113}
114
115static struct platform_driver samsungq10_driver = {
116 .driver = {
117 .name = KBUILD_MODNAME,
118 .owner = THIS_MODULE,
119 .pm = &samsungq10_pm_ops,
120 },
121 .probe = samsungq10_probe,
122 .remove = __devexit_p(samsungq10_remove),
123};
124
125static struct platform_device *samsungq10_device;
126
127static int __init dmi_check_callback(const struct dmi_system_id *id)
128{
129 printk(KERN_INFO KBUILD_MODNAME ": found model '%s'\n", id->ident);
130 return 1;
131}
132
133static struct dmi_system_id __initdata samsungq10_dmi_table[] = {
134 {
135 .ident = "Samsung Q10",
136 .matches = {
137 DMI_MATCH(DMI_SYS_VENDOR, "Samsung"),
138 DMI_MATCH(DMI_PRODUCT_NAME, "SQ10"),
139 },
140 .callback = dmi_check_callback,
141 },
142 {
143 .ident = "Samsung Q20",
144 .matches = {
145 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
146 DMI_MATCH(DMI_PRODUCT_NAME, "SENS Q20"),
147 },
148 .callback = dmi_check_callback,
149 },
150 {
151 .ident = "Samsung Q25",
152 .matches = {
153 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
154 DMI_MATCH(DMI_PRODUCT_NAME, "NQ25"),
155 },
156 .callback = dmi_check_callback,
157 },
158 {
159 .ident = "Dell Latitude X200",
160 .matches = {
161 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
162 DMI_MATCH(DMI_PRODUCT_NAME, "X200"),
163 },
164 .callback = dmi_check_callback,
165 },
166 { },
167};
168MODULE_DEVICE_TABLE(dmi, samsungq10_dmi_table);
169
170static int __init samsungq10_init(void)
171{
172 if (!force && !dmi_check_system(samsungq10_dmi_table))
173 return -ENODEV;
174
175 samsungq10_device = platform_create_bundle(&samsungq10_driver,
176 samsungq10_probe,
177 NULL, 0, NULL, 0);
178
179 if (IS_ERR(samsungq10_device))
180 return PTR_ERR(samsungq10_device);
181
182 return 0;
183}
184
185static void __exit samsungq10_exit(void)
186{
187 platform_device_unregister(samsungq10_device);
188 platform_driver_unregister(&samsungq10_driver);
189}
190
191module_init(samsungq10_init);
192module_exit(samsungq10_exit);
193
194MODULE_AUTHOR("Frederick van der Wyck <fvanderwyck@gmail.com>");
195MODULE_DESCRIPTION("Samsung Q10 Driver");
196MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 26c5b117df22..7bd829f247eb 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3186,8 +3186,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3186 KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ 3186 KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
3187 3187
3188 /* (assignments unknown, please report if found) */ 3188 /* (assignments unknown, please report if found) */
3189 KEY_UNKNOWN, KEY_UNKNOWN,
3190
3191 /*
3192 * The mic mute button only sends 0x1a. It does not
3193 * automatically mute the mic or change the mute light.
3194 */
3195 KEY_MICMUTE, /* 0x1a: Mic mute (since ?400 or so) */
3196
3197 /* (assignments unknown, please report if found) */
3189 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3198 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3190 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3199 KEY_UNKNOWN,
3191 }, 3200 },
3192 }; 3201 };
3193 3202