diff options
24 files changed, 608 insertions, 108 deletions
diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX index d399ae1fc724..a3b4f209e562 100644 --- a/Documentation/laptops/00-INDEX +++ b/Documentation/laptops/00-INDEX | |||
| @@ -18,3 +18,5 @@ sonypi.txt | |||
| 18 | - info on Linux Sony Programmable I/O Device support. | 18 | - info on Linux Sony Programmable I/O Device support. |
| 19 | thinkpad-acpi.txt | 19 | thinkpad-acpi.txt |
| 20 | - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver. | 20 | - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver. |
| 21 | toshiba_haps.txt | ||
| 22 | - information on the Toshiba HDD Active Protection Sensor driver. | ||
diff --git a/Documentation/laptops/toshiba_haps.txt b/Documentation/laptops/toshiba_haps.txt new file mode 100644 index 000000000000..11dbcfdc9e7a --- /dev/null +++ b/Documentation/laptops/toshiba_haps.txt | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | Kernel driver toshiba_haps | ||
| 2 | Toshiba HDD Active Protection Sensor | ||
| 3 | ==================================== | ||
| 4 | |||
| 5 | Author: Azael Avalos <coproscefalo@gmail.com> | ||
| 6 | |||
| 7 | |||
| 8 | 0. Contents | ||
| 9 | ----------- | ||
| 10 | |||
| 11 | 1. Description | ||
| 12 | 2. Interface | ||
| 13 | 3. Accelerometer axes | ||
| 14 | 4. Supported devices | ||
| 15 | 5. Usage | ||
| 16 | |||
| 17 | |||
| 18 | 1. Description | ||
| 19 | -------------- | ||
| 20 | |||
| 21 | This driver provides support for the accelerometer found in various Toshiba | ||
| 22 | laptops, being called "Toshiba HDD Protection - Shock Sensor" officialy, | ||
| 23 | and detects laptops automatically with this device. | ||
| 24 | On Windows, Toshiba provided software monitors this device and provides | ||
| 25 | automatic HDD protection (head unload) on sudden moves or harsh vibrations, | ||
| 26 | however, this driver only provides a notification via a sysfs file to let | ||
| 27 | userspace tools or daemons act accordingly, as well as providing a sysfs | ||
| 28 | file to set the desired protection level or sensor sensibility. | ||
| 29 | |||
| 30 | |||
| 31 | 2. Interface | ||
| 32 | ------------ | ||
| 33 | |||
| 34 | This device comes with 3 methods: | ||
| 35 | _STA - Checks existence of the device, returning Zero if the device does not | ||
| 36 | exists or is not supported. | ||
| 37 | PTLV - Sets the desired protection level. | ||
| 38 | RSSS - Shuts down the HDD protection interface for a few seconds, | ||
| 39 | then restores normal operation. | ||
| 40 | |||
| 41 | Note: | ||
| 42 | The presence of Solid State Drives (SSD) can make this driver to fail loading, | ||
| 43 | given the fact that such drives have no movable parts, and thus, not requiring | ||
| 44 | any "protection" as well as failing during the evaluation of the _STA method | ||
| 45 | found under this device. | ||
| 46 | |||
| 47 | |||
| 48 | 3. Accelerometer axes | ||
| 49 | --------------------- | ||
| 50 | |||
| 51 | This device does not report any axes, however, to query the sensor position | ||
| 52 | a couple HCI (Hardware Configuration Interface) calls (0x6D and 0xA6) are | ||
| 53 | provided to query such information, handled by the kernel module toshiba_acpi | ||
| 54 | since kernel version 3.15. | ||
| 55 | |||
| 56 | |||
| 57 | 4. Supported devices | ||
| 58 | -------------------- | ||
| 59 | |||
| 60 | This driver binds itself to the ACPI device TOS620A, and any Toshiba laptop | ||
| 61 | with this device is supported, given the fact that they have the presence of | ||
| 62 | conventional HDD and not only SSD, or a combination of both HDD and SSD. | ||
| 63 | |||
| 64 | |||
| 65 | 5. Usage | ||
| 66 | -------- | ||
| 67 | |||
| 68 | The sysfs files under /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS620A:00/ are: | ||
| 69 | protection_level - The protection_level is readable and writeable, and | ||
| 70 | provides a way to let userspace query the current protection | ||
| 71 | level, as well as set the desired protection level, the | ||
| 72 | available protection levels are: | ||
| 73 | 0 - Disabled | 1 - Low | 2 - Medium | 3 - High | ||
| 74 | reset_protection - The reset_protection entry is writeable only, being "1" | ||
| 75 | the only parameter it accepts, it is used to trigger | ||
| 76 | a reset of the protection interface. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 3bf3fc26c891..aefa94841ff3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -10017,7 +10017,7 @@ F: arch/x86/ | |||
| 10017 | X86 PLATFORM DRIVERS | 10017 | X86 PLATFORM DRIVERS |
| 10018 | M: Matthew Garrett <matthew.garrett@nebula.com> | 10018 | M: Matthew Garrett <matthew.garrett@nebula.com> |
| 10019 | L: platform-driver-x86@vger.kernel.org | 10019 | L: platform-driver-x86@vger.kernel.org |
| 10020 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git | 10020 | T: git git://cavan.codon.org.uk/platform-drivers-x86.git |
| 10021 | S: Maintained | 10021 | S: Maintained |
| 10022 | F: drivers/platform/x86/ | 10022 | F: drivers/platform/x86/ |
| 10023 | 10023 | ||
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 172f26ce59ac..3bbcbf12c1fb 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -652,6 +652,25 @@ config TOSHIBA_BT_RFKILL | |||
| 652 | If you have a modern Toshiba laptop with a Bluetooth and an | 652 | If you have a modern Toshiba laptop with a Bluetooth and an |
| 653 | RFKill switch (such as the Portege R500), say Y. | 653 | RFKill switch (such as the Portege R500), say Y. |
| 654 | 654 | ||
| 655 | config TOSHIBA_HAPS | ||
| 656 | tristate "Toshiba HDD Active Protection Sensor" | ||
| 657 | depends on ACPI | ||
| 658 | ---help--- | ||
| 659 | This driver adds support for the built-in accelerometer | ||
| 660 | found on recent Toshiba laptops equiped with HID TOS620A | ||
| 661 | device. | ||
| 662 | |||
| 663 | This driver receives ACPI notify events 0x80 when the sensor | ||
| 664 | detects a sudden move or a harsh vibration, as well as an | ||
| 665 | ACPI notify event 0x81 whenever the movement or vibration has | ||
| 666 | been stabilized. | ||
| 667 | |||
| 668 | Also provides sysfs entries to get/set the desired protection | ||
| 669 | level and reseting the HDD protection interface. | ||
| 670 | |||
| 671 | If you have a recent Toshiba laptop with a built-in accelerometer | ||
| 672 | device, say Y. | ||
| 673 | |||
| 655 | config ACPI_CMPC | 674 | config ACPI_CMPC |
| 656 | tristate "CMPC Laptop Extras" | 675 | tristate "CMPC Laptop Extras" |
| 657 | depends on X86 && ACPI | 676 | depends on X86 && ACPI |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index c4ca428fd3db..f82232b1fc4d 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
| @@ -38,6 +38,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o | |||
| 38 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o | 38 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o |
| 39 | 39 | ||
| 40 | obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o | 40 | obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o |
| 41 | obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o | ||
| 41 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o | 42 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o |
| 42 | obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o | 43 | obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o |
| 43 | obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o | 44 | obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index bbf78b2d6d93..96a0b75c52c9 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
| @@ -96,7 +96,7 @@ enum acer_wmi_event_ids { | |||
| 96 | WMID_ACCEL_EVENT = 0x5, | 96 | WMID_ACCEL_EVENT = 0x5, |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | static const struct key_entry acer_wmi_keymap[] = { | 99 | static const struct key_entry acer_wmi_keymap[] __initconst = { |
| 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, 0x04, {KEY_WLAN} }, /* WiFi */ |
| @@ -294,7 +294,7 @@ struct quirk_entry { | |||
| 294 | 294 | ||
| 295 | static struct quirk_entry *quirks; | 295 | static struct quirk_entry *quirks; |
| 296 | 296 | ||
| 297 | static void set_quirks(void) | 297 | static void __init set_quirks(void) |
| 298 | { | 298 | { |
| 299 | if (!interface) | 299 | if (!interface) |
| 300 | return; | 300 | return; |
| @@ -306,7 +306,7 @@ static void set_quirks(void) | |||
| 306 | interface->capability |= ACER_CAP_BRIGHTNESS; | 306 | interface->capability |= ACER_CAP_BRIGHTNESS; |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | static int dmi_matched(const struct dmi_system_id *dmi) | 309 | static int __init dmi_matched(const struct dmi_system_id *dmi) |
| 310 | { | 310 | { |
| 311 | quirks = dmi->driver_data; | 311 | quirks = dmi->driver_data; |
| 312 | return 1; | 312 | return 1; |
| @@ -337,7 +337,7 @@ static struct quirk_entry quirk_lenovo_ideapad_s205 = { | |||
| 337 | }; | 337 | }; |
| 338 | 338 | ||
| 339 | /* The Aspire One has a dummy ACPI-WMI interface - disable it */ | 339 | /* The Aspire One has a dummy ACPI-WMI interface - disable it */ |
| 340 | static struct dmi_system_id acer_blacklist[] = { | 340 | static const struct dmi_system_id acer_blacklist[] __initconst = { |
| 341 | { | 341 | { |
| 342 | .ident = "Acer Aspire One (SSD)", | 342 | .ident = "Acer Aspire One (SSD)", |
| 343 | .matches = { | 343 | .matches = { |
| @@ -355,7 +355,7 @@ static struct dmi_system_id acer_blacklist[] = { | |||
| 355 | {} | 355 | {} |
| 356 | }; | 356 | }; |
| 357 | 357 | ||
| 358 | static struct dmi_system_id acer_quirks[] = { | 358 | static const struct dmi_system_id acer_quirks[] __initconst = { |
| 359 | { | 359 | { |
| 360 | .callback = dmi_matched, | 360 | .callback = dmi_matched, |
| 361 | .ident = "Acer Aspire 1360", | 361 | .ident = "Acer Aspire 1360", |
| @@ -530,14 +530,15 @@ static struct dmi_system_id acer_quirks[] = { | |||
| 530 | {} | 530 | {} |
| 531 | }; | 531 | }; |
| 532 | 532 | ||
| 533 | static int video_set_backlight_video_vendor(const struct dmi_system_id *d) | 533 | static int __init |
| 534 | video_set_backlight_video_vendor(const struct dmi_system_id *d) | ||
| 534 | { | 535 | { |
| 535 | interface->capability &= ~ACER_CAP_BRIGHTNESS; | 536 | interface->capability &= ~ACER_CAP_BRIGHTNESS; |
| 536 | pr_info("Brightness must be controlled by generic video driver\n"); | 537 | pr_info("Brightness must be controlled by generic video driver\n"); |
| 537 | return 0; | 538 | return 0; |
| 538 | } | 539 | } |
| 539 | 540 | ||
| 540 | static const struct dmi_system_id video_vendor_dmi_table[] = { | 541 | static const struct dmi_system_id video_vendor_dmi_table[] __initconst = { |
| 541 | { | 542 | { |
| 542 | .callback = video_set_backlight_video_vendor, | 543 | .callback = video_set_backlight_video_vendor, |
| 543 | .ident = "Acer TravelMate 4750", | 544 | .ident = "Acer TravelMate 4750", |
| @@ -582,7 +583,7 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { | |||
| 582 | }; | 583 | }; |
| 583 | 584 | ||
| 584 | /* Find which quirks are needed for a particular vendor/ model pair */ | 585 | /* Find which quirks are needed for a particular vendor/ model pair */ |
| 585 | static void find_quirks(void) | 586 | static void __init find_quirks(void) |
| 586 | { | 587 | { |
| 587 | if (!force_series) { | 588 | if (!force_series) { |
| 588 | dmi_check_system(acer_quirks); | 589 | dmi_check_system(acer_quirks); |
| @@ -749,7 +750,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap) | |||
| 749 | return wmab_execute(&args, NULL); | 750 | return wmab_execute(&args, NULL); |
| 750 | } | 751 | } |
| 751 | 752 | ||
| 752 | static acpi_status AMW0_find_mailled(void) | 753 | static acpi_status __init AMW0_find_mailled(void) |
| 753 | { | 754 | { |
| 754 | struct wmab_args args; | 755 | struct wmab_args args; |
| 755 | struct wmab_ret ret; | 756 | struct wmab_ret ret; |
| @@ -781,16 +782,16 @@ static acpi_status AMW0_find_mailled(void) | |||
| 781 | return AE_OK; | 782 | return AE_OK; |
| 782 | } | 783 | } |
| 783 | 784 | ||
| 784 | static int AMW0_set_cap_acpi_check_device_found; | 785 | static int AMW0_set_cap_acpi_check_device_found __initdata; |
| 785 | 786 | ||
| 786 | static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, | 787 | static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, |
| 787 | u32 level, void *context, void **retval) | 788 | u32 level, void *context, void **retval) |
| 788 | { | 789 | { |
| 789 | AMW0_set_cap_acpi_check_device_found = 1; | 790 | AMW0_set_cap_acpi_check_device_found = 1; |
| 790 | return AE_OK; | 791 | return AE_OK; |
| 791 | } | 792 | } |
| 792 | 793 | ||
| 793 | static const struct acpi_device_id norfkill_ids[] = { | 794 | static const struct acpi_device_id norfkill_ids[] __initconst = { |
| 794 | { "VPC2004", 0}, | 795 | { "VPC2004", 0}, |
| 795 | { "IBM0068", 0}, | 796 | { "IBM0068", 0}, |
| 796 | { "LEN0068", 0}, | 797 | { "LEN0068", 0}, |
| @@ -798,7 +799,7 @@ static const struct acpi_device_id norfkill_ids[] = { | |||
| 798 | { "", 0}, | 799 | { "", 0}, |
| 799 | }; | 800 | }; |
| 800 | 801 | ||
| 801 | static int AMW0_set_cap_acpi_check_device(void) | 802 | static int __init AMW0_set_cap_acpi_check_device(void) |
| 802 | { | 803 | { |
| 803 | const struct acpi_device_id *id; | 804 | const struct acpi_device_id *id; |
| 804 | 805 | ||
| @@ -808,7 +809,7 @@ static int AMW0_set_cap_acpi_check_device(void) | |||
| 808 | return AMW0_set_cap_acpi_check_device_found; | 809 | return AMW0_set_cap_acpi_check_device_found; |
| 809 | } | 810 | } |
| 810 | 811 | ||
| 811 | static acpi_status AMW0_set_capabilities(void) | 812 | static acpi_status __init AMW0_set_capabilities(void) |
| 812 | { | 813 | { |
| 813 | struct wmab_args args; | 814 | struct wmab_args args; |
| 814 | struct wmab_ret ret; | 815 | struct wmab_ret ret; |
| @@ -1184,7 +1185,7 @@ static acpi_status wmid_v2_set_u32(u32 value, u32 cap) | |||
| 1184 | return wmid3_set_device_status(value, device); | 1185 | return wmid3_set_device_status(value, device); |
| 1185 | } | 1186 | } |
| 1186 | 1187 | ||
| 1187 | static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) | 1188 | static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d) |
| 1188 | { | 1189 | { |
| 1189 | struct hotkey_function_type_aa *type_aa; | 1190 | struct hotkey_function_type_aa *type_aa; |
| 1190 | 1191 | ||
| @@ -1209,7 +1210,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) | |||
| 1209 | commun_fn_key_number = type_aa->commun_fn_key_number; | 1210 | commun_fn_key_number = type_aa->commun_fn_key_number; |
| 1210 | } | 1211 | } |
| 1211 | 1212 | ||
| 1212 | static acpi_status WMID_set_capabilities(void) | 1213 | static acpi_status __init WMID_set_capabilities(void) |
| 1213 | { | 1214 | { |
| 1214 | struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; | 1215 | struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; |
| 1215 | union acpi_object *obj; | 1216 | union acpi_object *obj; |
| @@ -1658,7 +1659,7 @@ static ssize_t show_bool_threeg(struct device *dev, | |||
| 1658 | u32 result; \ | 1659 | u32 result; \ |
| 1659 | acpi_status status; | 1660 | acpi_status status; |
| 1660 | 1661 | ||
| 1661 | pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", | 1662 | pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", |
| 1662 | current->comm); | 1663 | current->comm); |
| 1663 | status = get_u32(&result, ACER_CAP_THREEG); | 1664 | status = get_u32(&result, ACER_CAP_THREEG); |
| 1664 | if (ACPI_SUCCESS(status)) | 1665 | if (ACPI_SUCCESS(status)) |
| @@ -1671,7 +1672,7 @@ static ssize_t set_bool_threeg(struct device *dev, | |||
| 1671 | { | 1672 | { |
| 1672 | u32 tmp = simple_strtoul(buf, NULL, 10); | 1673 | u32 tmp = simple_strtoul(buf, NULL, 10); |
| 1673 | acpi_status status = set_u32(tmp, ACER_CAP_THREEG); | 1674 | acpi_status status = set_u32(tmp, ACER_CAP_THREEG); |
| 1674 | pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", | 1675 | pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", |
| 1675 | current->comm); | 1676 | current->comm); |
| 1676 | if (ACPI_FAILURE(status)) | 1677 | if (ACPI_FAILURE(status)) |
| 1677 | return -EINVAL; | 1678 | return -EINVAL; |
| @@ -1683,7 +1684,7 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg, | |||
| 1683 | static ssize_t show_interface(struct device *dev, struct device_attribute *attr, | 1684 | static ssize_t show_interface(struct device *dev, struct device_attribute *attr, |
| 1684 | char *buf) | 1685 | char *buf) |
| 1685 | { | 1686 | { |
| 1686 | pr_info("This interface sysfs will be removed in 2012 - used by: %s\n", | 1687 | pr_info("This interface sysfs will be removed in 2014 - used by: %s\n", |
| 1687 | current->comm); | 1688 | current->comm); |
| 1688 | switch (interface->type) { | 1689 | switch (interface->type) { |
| 1689 | case ACER_AMW0: | 1690 | case ACER_AMW0: |
| @@ -1777,7 +1778,7 @@ static void acer_wmi_notify(u32 value, void *context) | |||
| 1777 | } | 1778 | } |
| 1778 | } | 1779 | } |
| 1779 | 1780 | ||
| 1780 | static acpi_status | 1781 | static acpi_status __init |
| 1781 | wmid3_set_lm_mode(struct lm_input_params *params, | 1782 | wmid3_set_lm_mode(struct lm_input_params *params, |
| 1782 | struct lm_return_value *return_value) | 1783 | struct lm_return_value *return_value) |
| 1783 | { | 1784 | { |
| @@ -1811,7 +1812,7 @@ wmid3_set_lm_mode(struct lm_input_params *params, | |||
| 1811 | return status; | 1812 | return status; |
| 1812 | } | 1813 | } |
| 1813 | 1814 | ||
| 1814 | static int acer_wmi_enable_ec_raw(void) | 1815 | static int __init acer_wmi_enable_ec_raw(void) |
| 1815 | { | 1816 | { |
| 1816 | struct lm_return_value return_value; | 1817 | struct lm_return_value return_value; |
| 1817 | acpi_status status; | 1818 | acpi_status status; |
| @@ -1834,7 +1835,7 @@ static int acer_wmi_enable_ec_raw(void) | |||
| 1834 | return status; | 1835 | return status; |
| 1835 | } | 1836 | } |
| 1836 | 1837 | ||
| 1837 | static int acer_wmi_enable_lm(void) | 1838 | static int __init acer_wmi_enable_lm(void) |
| 1838 | { | 1839 | { |
| 1839 | struct lm_return_value return_value; | 1840 | struct lm_return_value return_value; |
| 1840 | acpi_status status; | 1841 | acpi_status status; |
| @@ -2043,6 +2044,7 @@ static int acer_platform_remove(struct platform_device *device) | |||
| 2043 | return 0; | 2044 | return 0; |
| 2044 | } | 2045 | } |
| 2045 | 2046 | ||
| 2047 | #ifdef CONFIG_PM_SLEEP | ||
| 2046 | static int acer_suspend(struct device *dev) | 2048 | static int acer_suspend(struct device *dev) |
| 2047 | { | 2049 | { |
| 2048 | u32 value; | 2050 | u32 value; |
| @@ -2083,6 +2085,10 @@ static int acer_resume(struct device *dev) | |||
| 2083 | 2085 | ||
| 2084 | return 0; | 2086 | return 0; |
| 2085 | } | 2087 | } |
| 2088 | #else | ||
| 2089 | #define acer_suspend NULL | ||
| 2090 | #define acer_resume NULL | ||
| 2091 | #endif | ||
| 2086 | 2092 | ||
| 2087 | static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume); | 2093 | static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume); |
| 2088 | 2094 | ||
| @@ -2120,7 +2126,7 @@ static int remove_sysfs(struct platform_device *device) | |||
| 2120 | return 0; | 2126 | return 0; |
| 2121 | } | 2127 | } |
| 2122 | 2128 | ||
| 2123 | static int create_sysfs(void) | 2129 | static int __init create_sysfs(void) |
| 2124 | { | 2130 | { |
| 2125 | int retval = -ENOMEM; | 2131 | int retval = -ENOMEM; |
| 2126 | 2132 | ||
| @@ -2149,7 +2155,7 @@ static void remove_debugfs(void) | |||
| 2149 | debugfs_remove(interface->debug.root); | 2155 | debugfs_remove(interface->debug.root); |
| 2150 | } | 2156 | } |
| 2151 | 2157 | ||
| 2152 | static int create_debugfs(void) | 2158 | static int __init create_debugfs(void) |
| 2153 | { | 2159 | { |
| 2154 | interface->debug.root = debugfs_create_dir("acer-wmi", NULL); | 2160 | interface->debug.root = debugfs_create_dir("acer-wmi", NULL); |
| 2155 | if (!interface->debug.root) { | 2161 | if (!interface->debug.root) { |
diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 297b6640213f..c5af23b64438 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c | |||
| @@ -59,25 +59,33 @@ enum WMAX_CONTROL_STATES { | |||
| 59 | 59 | ||
| 60 | struct quirk_entry { | 60 | struct quirk_entry { |
| 61 | u8 num_zones; | 61 | u8 num_zones; |
| 62 | u8 hdmi_mux; | ||
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 64 | static struct quirk_entry *quirks; | 65 | static struct quirk_entry *quirks; |
| 65 | 66 | ||
| 66 | static struct quirk_entry quirk_unknown = { | 67 | static struct quirk_entry quirk_unknown = { |
| 67 | .num_zones = 2, | 68 | .num_zones = 2, |
| 69 | .hdmi_mux = 0, | ||
| 68 | }; | 70 | }; |
| 69 | 71 | ||
| 70 | static struct quirk_entry quirk_x51_family = { | 72 | static struct quirk_entry quirk_x51_family = { |
| 71 | .num_zones = 3, | 73 | .num_zones = 3, |
| 74 | .hdmi_mux = 0. | ||
| 72 | }; | 75 | }; |
| 73 | 76 | ||
| 74 | static int dmi_matched(const struct dmi_system_id *dmi) | 77 | static struct quirk_entry quirk_asm100 = { |
| 78 | .num_zones = 2, | ||
| 79 | .hdmi_mux = 1, | ||
| 80 | }; | ||
| 81 | |||
| 82 | static int __init dmi_matched(const struct dmi_system_id *dmi) | ||
| 75 | { | 83 | { |
| 76 | quirks = dmi->driver_data; | 84 | quirks = dmi->driver_data; |
| 77 | return 1; | 85 | return 1; |
| 78 | } | 86 | } |
| 79 | 87 | ||
| 80 | static struct dmi_system_id alienware_quirks[] = { | 88 | static const struct dmi_system_id alienware_quirks[] __initconst = { |
| 81 | { | 89 | { |
| 82 | .callback = dmi_matched, | 90 | .callback = dmi_matched, |
| 83 | .ident = "Alienware X51 R1", | 91 | .ident = "Alienware X51 R1", |
| @@ -96,6 +104,15 @@ static struct dmi_system_id alienware_quirks[] = { | |||
| 96 | }, | 104 | }, |
| 97 | .driver_data = &quirk_x51_family, | 105 | .driver_data = &quirk_x51_family, |
| 98 | }, | 106 | }, |
| 107 | { | ||
| 108 | .callback = dmi_matched, | ||
| 109 | .ident = "Alienware ASM100", | ||
| 110 | .matches = { | ||
| 111 | DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), | ||
| 112 | DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), | ||
| 113 | }, | ||
| 114 | .driver_data = &quirk_asm100, | ||
| 115 | }, | ||
| 99 | {} | 116 | {} |
| 100 | }; | 117 | }; |
| 101 | 118 | ||
| @@ -537,7 +554,8 @@ static struct attribute_group hdmi_attribute_group = { | |||
| 537 | 554 | ||
| 538 | static void remove_hdmi(struct platform_device *dev) | 555 | static void remove_hdmi(struct platform_device *dev) |
| 539 | { | 556 | { |
| 540 | sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); | 557 | if (quirks->hdmi_mux > 0) |
| 558 | sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); | ||
| 541 | } | 559 | } |
| 542 | 560 | ||
| 543 | static int create_hdmi(struct platform_device *dev) | 561 | static int create_hdmi(struct platform_device *dev) |
| @@ -583,7 +601,7 @@ static int __init alienware_wmi_init(void) | |||
| 583 | if (ret) | 601 | if (ret) |
| 584 | goto fail_platform_device2; | 602 | goto fail_platform_device2; |
| 585 | 603 | ||
| 586 | if (interface == WMAX) { | 604 | if (quirks->hdmi_mux > 0) { |
| 587 | ret = create_hdmi(platform_device); | 605 | ret = create_hdmi(platform_device); |
| 588 | if (ret) | 606 | if (ret) |
| 589 | goto fail_prep_hdmi; | 607 | goto fail_prep_hdmi; |
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index ddf0eefd862c..3a4951f46065 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c | |||
| @@ -70,17 +70,35 @@ static struct quirk_entry quirk_asus_x55u = { | |||
| 70 | .no_display_toggle = true, | 70 | .no_display_toggle = true, |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | static struct quirk_entry quirk_asus_x401u = { | 73 | static struct quirk_entry quirk_asus_wapf4 = { |
| 74 | .wapf = 4, | 74 | .wapf = 4, |
| 75 | }; | 75 | }; |
| 76 | 76 | ||
| 77 | static struct quirk_entry quirk_asus_x200ca = { | ||
| 78 | .wapf = 2, | ||
| 79 | }; | ||
| 80 | |||
| 77 | static int dmi_matched(const struct dmi_system_id *dmi) | 81 | static int dmi_matched(const struct dmi_system_id *dmi) |
| 78 | { | 82 | { |
| 79 | quirks = dmi->driver_data; | 83 | quirks = dmi->driver_data; |
| 80 | return 1; | 84 | return 1; |
| 81 | } | 85 | } |
| 82 | 86 | ||
| 83 | static struct dmi_system_id asus_quirks[] = { | 87 | static const struct dmi_system_id asus_quirks[] = { |
| 88 | { | ||
| 89 | .callback = dmi_matched, | ||
| 90 | .ident = "ASUSTeK COMPUTER INC. U32U", | ||
| 91 | .matches = { | ||
| 92 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
| 93 | DMI_MATCH(DMI_PRODUCT_NAME, "U32U"), | ||
| 94 | }, | ||
| 95 | /* | ||
| 96 | * Note this machine has a Brazos APU, and most Brazos Asus | ||
| 97 | * machines need quirk_asus_x55u / wmi_backlight_power but | ||
| 98 | * here acpi-video seems to work fine for backlight control. | ||
| 99 | */ | ||
| 100 | .driver_data = &quirk_asus_wapf4, | ||
| 101 | }, | ||
| 84 | { | 102 | { |
| 85 | .callback = dmi_matched, | 103 | .callback = dmi_matched, |
| 86 | .ident = "ASUSTeK COMPUTER INC. X401U", | 104 | .ident = "ASUSTeK COMPUTER INC. X401U", |
| @@ -97,7 +115,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 97 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 115 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 98 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), | 116 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), |
| 99 | }, | 117 | }, |
| 100 | .driver_data = &quirk_asus_x401u, | 118 | .driver_data = &quirk_asus_wapf4, |
| 101 | }, | 119 | }, |
| 102 | { | 120 | { |
| 103 | .callback = dmi_matched, | 121 | .callback = dmi_matched, |
| @@ -106,7 +124,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 106 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 124 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 107 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), | 125 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), |
| 108 | }, | 126 | }, |
| 109 | .driver_data = &quirk_asus_x401u, | 127 | .driver_data = &quirk_asus_wapf4, |
| 110 | }, | 128 | }, |
| 111 | { | 129 | { |
| 112 | .callback = dmi_matched, | 130 | .callback = dmi_matched, |
| @@ -124,7 +142,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 124 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 142 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 125 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), | 143 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), |
| 126 | }, | 144 | }, |
| 127 | .driver_data = &quirk_asus_x401u, | 145 | .driver_data = &quirk_asus_wapf4, |
| 128 | }, | 146 | }, |
| 129 | { | 147 | { |
| 130 | .callback = dmi_matched, | 148 | .callback = dmi_matched, |
| @@ -133,7 +151,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 133 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 151 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 134 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), | 152 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), |
| 135 | }, | 153 | }, |
| 136 | .driver_data = &quirk_asus_x401u, | 154 | .driver_data = &quirk_asus_wapf4, |
| 137 | }, | 155 | }, |
| 138 | { | 156 | { |
| 139 | .callback = dmi_matched, | 157 | .callback = dmi_matched, |
| @@ -142,7 +160,25 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 142 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 160 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 143 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), | 161 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), |
| 144 | }, | 162 | }, |
| 145 | .driver_data = &quirk_asus_x401u, | 163 | .driver_data = &quirk_asus_wapf4, |
| 164 | }, | ||
| 165 | { | ||
| 166 | .callback = dmi_matched, | ||
| 167 | .ident = "ASUSTeK COMPUTER INC. X550CC", | ||
| 168 | .matches = { | ||
| 169 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 170 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"), | ||
| 171 | }, | ||
| 172 | .driver_data = &quirk_asus_wapf4, | ||
| 173 | }, | ||
| 174 | { | ||
| 175 | .callback = dmi_matched, | ||
| 176 | .ident = "ASUSTeK COMPUTER INC. X550CL", | ||
| 177 | .matches = { | ||
| 178 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 179 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"), | ||
| 180 | }, | ||
| 181 | .driver_data = &quirk_asus_wapf4, | ||
| 146 | }, | 182 | }, |
| 147 | { | 183 | { |
| 148 | .callback = dmi_matched, | 184 | .callback = dmi_matched, |
| @@ -151,7 +187,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 151 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 187 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 152 | DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), | 188 | DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), |
| 153 | }, | 189 | }, |
| 154 | .driver_data = &quirk_asus_x401u, | 190 | .driver_data = &quirk_asus_wapf4, |
| 155 | }, | 191 | }, |
| 156 | { | 192 | { |
| 157 | .callback = dmi_matched, | 193 | .callback = dmi_matched, |
| @@ -160,7 +196,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 160 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 196 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 161 | DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), | 197 | DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), |
| 162 | }, | 198 | }, |
| 163 | .driver_data = &quirk_asus_x401u, | 199 | .driver_data = &quirk_asus_wapf4, |
| 164 | }, | 200 | }, |
| 165 | { | 201 | { |
| 166 | .callback = dmi_matched, | 202 | .callback = dmi_matched, |
| @@ -178,7 +214,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 178 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 214 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 179 | DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), | 215 | DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), |
| 180 | }, | 216 | }, |
| 181 | .driver_data = &quirk_asus_x401u, | 217 | .driver_data = &quirk_asus_wapf4, |
| 182 | }, | 218 | }, |
| 183 | { | 219 | { |
| 184 | .callback = dmi_matched, | 220 | .callback = dmi_matched, |
| @@ -187,7 +223,16 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 187 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 223 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 188 | DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), | 224 | DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), |
| 189 | }, | 225 | }, |
| 190 | .driver_data = &quirk_asus_x401u, | 226 | .driver_data = &quirk_asus_wapf4, |
| 227 | }, | ||
| 228 | { | ||
| 229 | .callback = dmi_matched, | ||
| 230 | .ident = "ASUSTeK COMPUTER INC. X75VBP", | ||
| 231 | .matches = { | ||
| 232 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 233 | DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"), | ||
| 234 | }, | ||
| 235 | .driver_data = &quirk_asus_wapf4, | ||
| 191 | }, | 236 | }, |
| 192 | { | 237 | { |
| 193 | .callback = dmi_matched, | 238 | .callback = dmi_matched, |
| @@ -196,7 +241,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 196 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 241 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 197 | DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), | 242 | DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), |
| 198 | }, | 243 | }, |
| 199 | .driver_data = &quirk_asus_x401u, | 244 | .driver_data = &quirk_asus_wapf4, |
| 200 | }, | 245 | }, |
| 201 | { | 246 | { |
| 202 | .callback = dmi_matched, | 247 | .callback = dmi_matched, |
| @@ -205,7 +250,16 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 205 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 250 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 206 | DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), | 251 | DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), |
| 207 | }, | 252 | }, |
| 208 | .driver_data = &quirk_asus_x401u, | 253 | .driver_data = &quirk_asus_wapf4, |
| 254 | }, | ||
| 255 | { | ||
| 256 | .callback = dmi_matched, | ||
| 257 | .ident = "ASUSTeK COMPUTER INC. X200CA", | ||
| 258 | .matches = { | ||
| 259 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 260 | DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"), | ||
| 261 | }, | ||
| 262 | .driver_data = &quirk_asus_x200ca, | ||
| 209 | }, | 263 | }, |
| 210 | {}, | 264 | {}, |
| 211 | }; | 265 | }; |
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 3c6ccedc82b6..21fc932da3a1 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include <linux/platform_device.h> | 46 | #include <linux/platform_device.h> |
| 47 | #include <linux/thermal.h> | 47 | #include <linux/thermal.h> |
| 48 | #include <linux/acpi.h> | 48 | #include <linux/acpi.h> |
| 49 | #include <linux/dmi.h> | ||
| 49 | #include <acpi/video.h> | 50 | #include <acpi/video.h> |
| 50 | 51 | ||
| 51 | #include "asus-wmi.h" | 52 | #include "asus-wmi.h" |
| @@ -554,7 +555,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) | |||
| 554 | goto error; | 555 | goto error; |
| 555 | } | 556 | } |
| 556 | 557 | ||
| 557 | if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) { | 558 | if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) { |
| 558 | INIT_WORK(&asus->wlan_led_work, wlan_led_update); | 559 | INIT_WORK(&asus->wlan_led_work, wlan_led_update); |
| 559 | 560 | ||
| 560 | asus->wlan_led.name = "asus::wlan"; | 561 | asus->wlan_led.name = "asus::wlan"; |
| @@ -884,7 +885,7 @@ static int asus_new_rfkill(struct asus_wmi *asus, | |||
| 884 | return -EINVAL; | 885 | return -EINVAL; |
| 885 | 886 | ||
| 886 | if ((dev_id == ASUS_WMI_DEVID_WLAN) && | 887 | if ((dev_id == ASUS_WMI_DEVID_WLAN) && |
| 887 | (asus->driver->quirks->wapf == 4)) | 888 | (asus->driver->quirks->wapf > 0)) |
| 888 | rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); | 889 | rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); |
| 889 | 890 | ||
| 890 | rfkill_init_sw_state(*rfkill, !result); | 891 | rfkill_init_sw_state(*rfkill, !result); |
| @@ -1270,10 +1271,7 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus) | |||
| 1270 | int power; | 1271 | int power; |
| 1271 | 1272 | ||
| 1272 | max = read_brightness_max(asus); | 1273 | max = read_brightness_max(asus); |
| 1273 | 1274 | if (max < 0) | |
| 1274 | if (max == -ENODEV) | ||
| 1275 | max = 0; | ||
| 1276 | else if (max < 0) | ||
| 1277 | return max; | 1275 | return max; |
| 1278 | 1276 | ||
| 1279 | power = read_backlight_power(asus); | 1277 | power = read_backlight_power(asus); |
| @@ -1734,6 +1732,7 @@ static int asus_wmi_add(struct platform_device *pdev) | |||
| 1734 | struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); | 1732 | struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); |
| 1735 | struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); | 1733 | struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); |
| 1736 | struct asus_wmi *asus; | 1734 | struct asus_wmi *asus; |
| 1735 | const char *chassis_type; | ||
| 1737 | acpi_status status; | 1736 | acpi_status status; |
| 1738 | int err; | 1737 | int err; |
| 1739 | u32 result; | 1738 | u32 result; |
| @@ -1770,6 +1769,11 @@ static int asus_wmi_add(struct platform_device *pdev) | |||
| 1770 | if (err) | 1769 | if (err) |
| 1771 | goto fail_rfkill; | 1770 | goto fail_rfkill; |
| 1772 | 1771 | ||
| 1772 | /* Some Asus desktop boards export an acpi-video backlight interface, | ||
| 1773 | stop this from showing up */ | ||
| 1774 | chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); | ||
| 1775 | if (chassis_type && !strcmp(chassis_type, "3")) | ||
| 1776 | acpi_video_dmi_promote_vendor(); | ||
| 1773 | if (asus->driver->quirks->wmi_backlight_power) | 1777 | if (asus->driver->quirks->wmi_backlight_power) |
| 1774 | acpi_video_dmi_promote_vendor(); | 1778 | acpi_video_dmi_promote_vendor(); |
| 1775 | if (!acpi_video_backlight_support()) { | 1779 | if (!acpi_video_backlight_support()) { |
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 7297df2ebf50..26bfd7bb5c13 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c | |||
| @@ -1028,7 +1028,7 @@ static int compal_probe(struct platform_device *pdev) | |||
| 1028 | return err; | 1028 | return err; |
| 1029 | 1029 | ||
| 1030 | hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, | 1030 | hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, |
| 1031 | DRIVER_NAME, data, | 1031 | "compal", data, |
| 1032 | compal_hwmon_groups); | 1032 | compal_hwmon_groups); |
| 1033 | if (IS_ERR(hwmon_dev)) { | 1033 | if (IS_ERR(hwmon_dev)) { |
| 1034 | err = PTR_ERR(hwmon_dev); | 1034 | err = PTR_ERR(hwmon_dev); |
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index fed4111ac31a..233d2ee598a6 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
| @@ -70,7 +70,7 @@ static struct quirk_entry quirk_dell_vostro_v130 = { | |||
| 70 | .touchpad_led = 1, | 70 | .touchpad_led = 1, |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | static int dmi_matched(const struct dmi_system_id *dmi) | 73 | static int __init dmi_matched(const struct dmi_system_id *dmi) |
| 74 | { | 74 | { |
| 75 | quirks = dmi->driver_data; | 75 | quirks = dmi->driver_data; |
| 76 | return 1; | 76 | return 1; |
| @@ -123,7 +123,7 @@ static const struct dmi_system_id dell_device_table[] __initconst = { | |||
| 123 | }; | 123 | }; |
| 124 | MODULE_DEVICE_TABLE(dmi, dell_device_table); | 124 | MODULE_DEVICE_TABLE(dmi, dell_device_table); |
| 125 | 125 | ||
| 126 | static struct dmi_system_id dell_quirks[] = { | 126 | static const struct dmi_system_id dell_quirks[] __initconst = { |
| 127 | { | 127 | { |
| 128 | .callback = dmi_matched, | 128 | .callback = dmi_matched, |
| 129 | .ident = "Dell Vostro V130", | 129 | .ident = "Dell Vostro V130", |
| @@ -780,7 +780,7 @@ static struct led_classdev touchpad_led = { | |||
| 780 | .flags = LED_CORE_SUSPENDRESUME, | 780 | .flags = LED_CORE_SUSPENDRESUME, |
| 781 | }; | 781 | }; |
| 782 | 782 | ||
| 783 | static int touchpad_led_init(struct device *dev) | 783 | static int __init touchpad_led_init(struct device *dev) |
| 784 | { | 784 | { |
| 785 | return led_classdev_register(dev, &touchpad_led); | 785 | return led_classdev_register(dev, &touchpad_led); |
| 786 | } | 786 | } |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9b0c57cd1d4a..bd533c22be57 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -1053,20 +1053,20 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf) | |||
| 1053 | return sprintf(buf, "%d\n", get()); | 1053 | return sprintf(buf, "%d\n", get()); |
| 1054 | } | 1054 | } |
| 1055 | 1055 | ||
| 1056 | #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \ | 1056 | #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _get, _set) \ |
| 1057 | static ssize_t show_##_name(struct device *dev, \ | 1057 | static ssize_t show_##_name(struct device *dev, \ |
| 1058 | struct device_attribute *attr, \ | 1058 | struct device_attribute *attr, \ |
| 1059 | char *buf) \ | 1059 | char *buf) \ |
| 1060 | { \ | 1060 | { \ |
| 1061 | return show_sys_hwmon(_set, buf); \ | 1061 | return show_sys_hwmon(_get, buf); \ |
| 1062 | } \ | 1062 | } \ |
| 1063 | static ssize_t store_##_name(struct device *dev, \ | 1063 | static ssize_t store_##_name(struct device *dev, \ |
| 1064 | struct device_attribute *attr, \ | 1064 | struct device_attribute *attr, \ |
| 1065 | const char *buf, size_t count) \ | 1065 | const char *buf, size_t count) \ |
| 1066 | { \ | 1066 | { \ |
| 1067 | return store_sys_hwmon(_get, buf, count); \ | 1067 | return store_sys_hwmon(_set, buf, count); \ |
| 1068 | } \ | 1068 | } \ |
| 1069 | static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name); | 1069 | static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name) |
| 1070 | 1070 | ||
| 1071 | EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); | 1071 | EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); |
| 1072 | EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, | 1072 | EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, |
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 6112933f6278..14fd2ecb06a1 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c | |||
| @@ -145,7 +145,7 @@ static int dmi_matched(const struct dmi_system_id *dmi) | |||
| 145 | return 1; | 145 | return 1; |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static struct dmi_system_id asus_quirks[] = { | 148 | static const struct dmi_system_id asus_quirks[] = { |
| 149 | { | 149 | { |
| 150 | .callback = dmi_matched, | 150 | .callback = dmi_matched, |
| 151 | .ident = "ASUSTeK Computer INC. 1000H", | 151 | .ident = "ASUSTeK Computer INC. 1000H", |
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index e6f336270c21..87aa28c4280f 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c | |||
| @@ -129,15 +129,14 @@ | |||
| 129 | #define FUJLAPTOP_DBG_INFO 0x0004 | 129 | #define FUJLAPTOP_DBG_INFO 0x0004 |
| 130 | #define FUJLAPTOP_DBG_TRACE 0x0008 | 130 | #define FUJLAPTOP_DBG_TRACE 0x0008 |
| 131 | 131 | ||
| 132 | #define dbg_printk(a_dbg_level, format, arg...) \ | 132 | #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG |
| 133 | #define vdbg_printk(a_dbg_level, format, arg...) \ | ||
| 133 | do { if (dbg_level & a_dbg_level) \ | 134 | do { if (dbg_level & a_dbg_level) \ |
| 134 | printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ | 135 | printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ |
| 135 | } while (0) | 136 | } while (0) |
| 136 | #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG | ||
| 137 | #define vdbg_printk(a_dbg_level, format, arg...) \ | ||
| 138 | dbg_printk(a_dbg_level, format, ## arg) | ||
| 139 | #else | 137 | #else |
| 140 | #define vdbg_printk(a_dbg_level, format, arg...) | 138 | #define vdbg_printk(a_dbg_level, format, arg...) \ |
| 139 | do { } while (0) | ||
| 141 | #endif | 140 | #endif |
| 142 | 141 | ||
| 143 | /* Device controlling the backlight and associated keys */ | 142 | /* Device controlling the backlight and associated keys */ |
| @@ -564,7 +563,7 @@ static struct platform_driver fujitsupf_driver = { | |||
| 564 | } | 563 | } |
| 565 | }; | 564 | }; |
| 566 | 565 | ||
| 567 | static void dmi_check_cb_common(const struct dmi_system_id *id) | 566 | static void __init dmi_check_cb_common(const struct dmi_system_id *id) |
| 568 | { | 567 | { |
| 569 | pr_info("Identified laptop model '%s'\n", id->ident); | 568 | pr_info("Identified laptop model '%s'\n", id->ident); |
| 570 | if (use_alt_lcd_levels == -1) { | 569 | if (use_alt_lcd_levels == -1) { |
| @@ -578,7 +577,7 @@ static void dmi_check_cb_common(const struct dmi_system_id *id) | |||
| 578 | } | 577 | } |
| 579 | } | 578 | } |
| 580 | 579 | ||
| 581 | static int dmi_check_cb_s6410(const struct dmi_system_id *id) | 580 | static int __init dmi_check_cb_s6410(const struct dmi_system_id *id) |
| 582 | { | 581 | { |
| 583 | dmi_check_cb_common(id); | 582 | dmi_check_cb_common(id); |
| 584 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ | 583 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ |
| @@ -586,7 +585,7 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) | |||
| 586 | return 1; | 585 | return 1; |
| 587 | } | 586 | } |
| 588 | 587 | ||
| 589 | static int dmi_check_cb_s6420(const struct dmi_system_id *id) | 588 | static int __init dmi_check_cb_s6420(const struct dmi_system_id *id) |
| 590 | { | 589 | { |
| 591 | dmi_check_cb_common(id); | 590 | dmi_check_cb_common(id); |
| 592 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ | 591 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ |
| @@ -594,7 +593,7 @@ static int dmi_check_cb_s6420(const struct dmi_system_id *id) | |||
| 594 | return 1; | 593 | return 1; |
| 595 | } | 594 | } |
| 596 | 595 | ||
| 597 | static int dmi_check_cb_p8010(const struct dmi_system_id *id) | 596 | static int __init dmi_check_cb_p8010(const struct dmi_system_id *id) |
| 598 | { | 597 | { |
| 599 | dmi_check_cb_common(id); | 598 | dmi_check_cb_common(id); |
| 600 | fujitsu->keycode1 = KEY_HELP; /* "Support" */ | 599 | fujitsu->keycode1 = KEY_HELP; /* "Support" */ |
| @@ -603,7 +602,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id) | |||
| 603 | return 1; | 602 | return 1; |
| 604 | } | 603 | } |
| 605 | 604 | ||
| 606 | static struct dmi_system_id fujitsu_dmi_table[] = { | 605 | static const struct dmi_system_id fujitsu_dmi_table[] __initconst = { |
| 607 | { | 606 | { |
| 608 | .ident = "Fujitsu Siemens S6410", | 607 | .ident = "Fujitsu Siemens S6410", |
| 609 | .matches = { | 608 | .matches = { |
diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index c3784baceae3..53bdbb01bd3f 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c | |||
| @@ -315,21 +315,21 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id) | |||
| 315 | return IRQ_HANDLED; | 315 | return IRQ_HANDLED; |
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | static void fujitsu_dmi_common(const struct dmi_system_id *dmi) | 318 | static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi) |
| 319 | { | 319 | { |
| 320 | pr_info("%s\n", dmi->ident); | 320 | pr_info("%s\n", dmi->ident); |
| 321 | memcpy(fujitsu.config.keymap, dmi->driver_data, | 321 | memcpy(fujitsu.config.keymap, dmi->driver_data, |
| 322 | sizeof(fujitsu.config.keymap)); | 322 | sizeof(fujitsu.config.keymap)); |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | static int fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) | 325 | static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) |
| 326 | { | 326 | { |
| 327 | fujitsu_dmi_common(dmi); | 327 | fujitsu_dmi_common(dmi); |
| 328 | fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; | 328 | fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; |
| 329 | return 1; | 329 | return 1; |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | static int fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) | 332 | static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) |
| 333 | { | 333 | { |
| 334 | fujitsu_dmi_common(dmi); | 334 | fujitsu_dmi_common(dmi); |
| 335 | fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; | 335 | fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 484a8673b835..4c559640dcba 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
| @@ -295,7 +295,7 @@ static int hp_wmi_tablet_state(void) | |||
| 295 | return (state & 0x4) ? 1 : 0; | 295 | return (state & 0x4) ? 1 : 0; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static int hp_wmi_bios_2009_later(void) | 298 | static int __init hp_wmi_bios_2009_later(void) |
| 299 | { | 299 | { |
| 300 | int state = 0; | 300 | int state = 0; |
| 301 | int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, | 301 | int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, |
| @@ -704,7 +704,7 @@ static void cleanup_sysfs(struct platform_device *device) | |||
| 704 | device_remove_file(&device->dev, &dev_attr_postcode); | 704 | device_remove_file(&device->dev, &dev_attr_postcode); |
| 705 | } | 705 | } |
| 706 | 706 | ||
| 707 | static int hp_wmi_rfkill_setup(struct platform_device *device) | 707 | static int __init hp_wmi_rfkill_setup(struct platform_device *device) |
| 708 | { | 708 | { |
| 709 | int err; | 709 | int err; |
| 710 | int wireless = 0; | 710 | int wireless = 0; |
| @@ -806,7 +806,7 @@ register_wifi_error: | |||
| 806 | return err; | 806 | return err; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | static int hp_wmi_rfkill2_setup(struct platform_device *device) | 809 | static int __init hp_wmi_rfkill2_setup(struct platform_device *device) |
| 810 | { | 810 | { |
| 811 | int err, i; | 811 | int err, i; |
| 812 | struct bios_rfkill2_state state; | 812 | struct bios_rfkill2_state state; |
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 3dc934438c28..13e14ec1d3d7 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c | |||
| @@ -74,7 +74,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev, | |||
| 74 | /* HP-specific accelerometer driver ------------------------------------ */ | 74 | /* HP-specific accelerometer driver ------------------------------------ */ |
| 75 | 75 | ||
| 76 | /* For automatic insertion of the module */ | 76 | /* For automatic insertion of the module */ |
| 77 | static struct acpi_device_id lis3lv02d_device_ids[] = { | 77 | static const struct acpi_device_id lis3lv02d_device_ids[] = { |
| 78 | {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ | 78 | {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ |
| 79 | {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ | 79 | {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ |
| 80 | {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ | 80 | {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ |
| @@ -192,7 +192,7 @@ DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3); | |||
| 192 | }, \ | 192 | }, \ |
| 193 | .driver_data = &lis3lv02d_axis_##_axis \ | 193 | .driver_data = &lis3lv02d_axis_##_axis \ |
| 194 | } | 194 | } |
| 195 | static struct dmi_system_id lis3lv02d_dmi_ids[] = { | 195 | static const struct dmi_system_id lis3lv02d_dmi_ids[] = { |
| 196 | /* product names are truncated to match all kinds of a same model */ | 196 | /* product names are truncated to match all kinds of a same model */ |
| 197 | AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), | 197 | AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), |
| 198 | AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), | 198 | AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), |
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index b4c495a62eec..fc468a3d95ce 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
| @@ -87,6 +87,8 @@ struct ideapad_private { | |||
| 87 | struct backlight_device *blightdev; | 87 | struct backlight_device *blightdev; |
| 88 | struct dentry *debug; | 88 | struct dentry *debug; |
| 89 | unsigned long cfg; | 89 | unsigned long cfg; |
| 90 | bool has_hw_rfkill_switch; | ||
| 91 | bool has_touchpad_control; | ||
| 90 | }; | 92 | }; |
| 91 | 93 | ||
| 92 | static bool no_bt_rfkill; | 94 | static bool no_bt_rfkill; |
| @@ -439,7 +441,7 @@ static umode_t ideapad_is_visible(struct kobject *kobj, | |||
| 439 | return supported ? attr->mode : 0; | 441 | return supported ? attr->mode : 0; |
| 440 | } | 442 | } |
| 441 | 443 | ||
| 442 | static struct attribute_group ideapad_attribute_group = { | 444 | static const struct attribute_group ideapad_attribute_group = { |
| 443 | .is_visible = ideapad_is_visible, | 445 | .is_visible = ideapad_is_visible, |
| 444 | .attrs = ideapad_attributes | 446 | .attrs = ideapad_attributes |
| 445 | }; | 447 | }; |
| @@ -454,7 +456,7 @@ struct ideapad_rfk_data { | |||
| 454 | int type; | 456 | int type; |
| 455 | }; | 457 | }; |
| 456 | 458 | ||
| 457 | const struct ideapad_rfk_data ideapad_rfk_data[] = { | 459 | const const struct ideapad_rfk_data ideapad_rfk_data[] = { |
| 458 | { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, | 460 | { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, |
| 459 | { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, | 461 | { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, |
| 460 | { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, | 462 | { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, |
| @@ -473,12 +475,14 @@ static struct rfkill_ops ideapad_rfk_ops = { | |||
| 473 | 475 | ||
| 474 | static void ideapad_sync_rfk_state(struct ideapad_private *priv) | 476 | static void ideapad_sync_rfk_state(struct ideapad_private *priv) |
| 475 | { | 477 | { |
| 476 | unsigned long hw_blocked; | 478 | unsigned long hw_blocked = 0; |
| 477 | int i; | 479 | int i; |
| 478 | 480 | ||
| 479 | if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) | 481 | if (priv->has_hw_rfkill_switch) { |
| 480 | return; | 482 | if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) |
| 481 | hw_blocked = !hw_blocked; | 483 | return; |
| 484 | hw_blocked = !hw_blocked; | ||
| 485 | } | ||
| 482 | 486 | ||
| 483 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 487 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) |
| 484 | if (priv->rfk[i]) | 488 | if (priv->rfk[i]) |
| @@ -763,6 +767,9 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv) | |||
| 763 | { | 767 | { |
| 764 | unsigned long value; | 768 | unsigned long value; |
| 765 | 769 | ||
| 770 | if (!priv->has_touchpad_control) | ||
| 771 | return; | ||
| 772 | |||
| 766 | /* Without reading from EC touchpad LED doesn't switch state */ | 773 | /* Without reading from EC touchpad LED doesn't switch state */ |
| 767 | if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { | 774 | if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { |
| 768 | /* Some IdeaPads don't really turn off touchpad - they only | 775 | /* Some IdeaPads don't really turn off touchpad - they only |
| @@ -821,14 +828,39 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) | |||
| 821 | } | 828 | } |
| 822 | } | 829 | } |
| 823 | 830 | ||
| 824 | /* Blacklist for devices where the ideapad rfkill interface does not work */ | 831 | /* |
| 825 | static struct dmi_system_id rfkill_blacklist[] = { | 832 | * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF |
| 826 | /* The Lenovo Yoga 2 11 always reports everything as blocked */ | 833 | * always results in 0 on these models, causing ideapad_laptop to wrongly |
| 834 | * report all radios as hardware-blocked. | ||
| 835 | */ | ||
| 836 | static struct dmi_system_id no_hw_rfkill_list[] = { | ||
| 827 | { | 837 | { |
| 828 | .ident = "Lenovo Yoga 2 11", | 838 | .ident = "Lenovo Yoga 2 11 / 13 / Pro", |
| 829 | .matches = { | 839 | .matches = { |
| 830 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 840 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 831 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), | 841 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), |
| 842 | }, | ||
| 843 | }, | ||
| 844 | {} | ||
| 845 | }; | ||
| 846 | |||
| 847 | /* | ||
| 848 | * Some models don't offer touchpad ctrl through the ideapad interface, causing | ||
| 849 | * ideapad_sync_touchpad_state to send wrong touchpad enable/disable events. | ||
| 850 | */ | ||
| 851 | static struct dmi_system_id no_touchpad_ctrl_list[] = { | ||
| 852 | { | ||
| 853 | .ident = "Lenovo Yoga 1 series", | ||
| 854 | .matches = { | ||
| 855 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 856 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga"), | ||
| 857 | }, | ||
| 858 | }, | ||
| 859 | { | ||
| 860 | .ident = "Lenovo Yoga 2 11 / 13 / Pro", | ||
| 861 | .matches = { | ||
| 862 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 863 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), | ||
| 832 | }, | 864 | }, |
| 833 | }, | 865 | }, |
| 834 | {} | 866 | {} |
| @@ -856,6 +888,8 @@ static int ideapad_acpi_add(struct platform_device *pdev) | |||
| 856 | priv->cfg = cfg; | 888 | priv->cfg = cfg; |
| 857 | priv->adev = adev; | 889 | priv->adev = adev; |
| 858 | priv->platform_device = pdev; | 890 | priv->platform_device = pdev; |
| 891 | priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list); | ||
| 892 | priv->has_touchpad_control = !dmi_check_system(no_touchpad_ctrl_list); | ||
| 859 | 893 | ||
| 860 | ret = ideapad_sysfs_init(priv); | 894 | ret = ideapad_sysfs_init(priv); |
| 861 | if (ret) | 895 | if (ret) |
| @@ -869,11 +903,17 @@ static int ideapad_acpi_add(struct platform_device *pdev) | |||
| 869 | if (ret) | 903 | if (ret) |
| 870 | goto input_failed; | 904 | goto input_failed; |
| 871 | 905 | ||
| 872 | if (!dmi_check_system(rfkill_blacklist)) { | 906 | /* |
| 873 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 907 | * On some models without a hw-switch (the yoga 2 13 at least) |
| 874 | if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) | 908 | * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. |
| 875 | ideapad_register_rfkill(priv, i); | 909 | */ |
| 876 | } | 910 | if (!priv->has_hw_rfkill_switch) |
| 911 | write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); | ||
| 912 | |||
| 913 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | ||
| 914 | if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) | ||
| 915 | ideapad_register_rfkill(priv, i); | ||
| 916 | |||
| 877 | ideapad_sync_rfk_state(priv); | 917 | ideapad_sync_rfk_state(priv); |
| 878 | ideapad_sync_touchpad_state(priv); | 918 | ideapad_sync_touchpad_state(priv); |
| 879 | 919 | ||
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index a0d1f576cf40..c0242ed13d9e 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c | |||
| @@ -269,7 +269,7 @@ struct ips_mcp_limits { | |||
| 269 | 269 | ||
| 270 | /* Max temps are -10 degrees C to avoid PROCHOT# */ | 270 | /* Max temps are -10 degrees C to avoid PROCHOT# */ |
| 271 | 271 | ||
| 272 | struct ips_mcp_limits ips_sv_limits = { | 272 | static struct ips_mcp_limits ips_sv_limits = { |
| 273 | .mcp_power_limit = 35000, | 273 | .mcp_power_limit = 35000, |
| 274 | .core_power_limit = 29000, | 274 | .core_power_limit = 29000, |
| 275 | .mch_power_limit = 20000, | 275 | .mch_power_limit = 20000, |
| @@ -277,7 +277,7 @@ struct ips_mcp_limits ips_sv_limits = { | |||
| 277 | .mch_temp_limit = 90 | 277 | .mch_temp_limit = 90 |
| 278 | }; | 278 | }; |
| 279 | 279 | ||
| 280 | struct ips_mcp_limits ips_lv_limits = { | 280 | static struct ips_mcp_limits ips_lv_limits = { |
| 281 | .mcp_power_limit = 25000, | 281 | .mcp_power_limit = 25000, |
| 282 | .core_power_limit = 21000, | 282 | .core_power_limit = 21000, |
| 283 | .mch_power_limit = 13000, | 283 | .mch_power_limit = 13000, |
| @@ -285,7 +285,7 @@ struct ips_mcp_limits ips_lv_limits = { | |||
| 285 | .mch_temp_limit = 90 | 285 | .mch_temp_limit = 90 |
| 286 | }; | 286 | }; |
| 287 | 287 | ||
| 288 | struct ips_mcp_limits ips_ulv_limits = { | 288 | static struct ips_mcp_limits ips_ulv_limits = { |
| 289 | .mcp_power_limit = 18000, | 289 | .mcp_power_limit = 18000, |
| 290 | .core_power_limit = 14000, | 290 | .core_power_limit = 14000, |
| 291 | .mch_power_limit = 11000, | 291 | .mch_power_limit = 11000, |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 9c5a07417b2b..26ad9ff12ac5 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
| @@ -2389,7 +2389,7 @@ static int sony_nc_lid_resume_setup(struct platform_device *pd, | |||
| 2389 | lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; | 2389 | lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; |
| 2390 | } | 2390 | } |
| 2391 | for (i = 0; i < LID_RESUME_MAX && | 2391 | for (i = 0; i < LID_RESUME_MAX && |
| 2392 | lid_ctl->attrs[LID_RESUME_S3].attr.name; i++) { | 2392 | lid_ctl->attrs[i].attr.name; i++) { |
| 2393 | result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); | 2393 | result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); |
| 2394 | if (result) | 2394 | if (result) |
| 2395 | goto liderror; | 2395 | goto liderror; |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d82f196e3cfe..3bbc6eb60de5 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -3174,7 +3174,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 3174 | KEY_UNKNOWN, | 3174 | KEY_UNKNOWN, |
| 3175 | 3175 | ||
| 3176 | /* Extra keys in use since the X240 / T440 / T540 */ | 3176 | /* Extra keys in use since the X240 / T440 / T540 */ |
| 3177 | KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_COMPUTER, | 3177 | KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE, |
| 3178 | }, | 3178 | }, |
| 3179 | }; | 3179 | }; |
| 3180 | 3180 | ||
| @@ -6144,7 +6144,7 @@ static int brightness_set(unsigned int value) | |||
| 6144 | { | 6144 | { |
| 6145 | int res; | 6145 | int res; |
| 6146 | 6146 | ||
| 6147 | if (value > bright_maxlvl || value < 0) | 6147 | if (value > bright_maxlvl) |
| 6148 | return -EINVAL; | 6148 | return -EINVAL; |
| 6149 | 6149 | ||
| 6150 | vdbg_printk(TPACPI_DBG_BRGHT, | 6150 | vdbg_printk(TPACPI_DBG_BRGHT, |
| @@ -6860,7 +6860,7 @@ static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, | |||
| 6860 | return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); | 6860 | return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); |
| 6861 | } | 6861 | } |
| 6862 | 6862 | ||
| 6863 | static struct snd_kcontrol_new volume_alsa_control_vol = { | 6863 | static struct snd_kcontrol_new volume_alsa_control_vol __initdata = { |
| 6864 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 6864 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 6865 | .name = "Console Playback Volume", | 6865 | .name = "Console Playback Volume", |
| 6866 | .index = 0, | 6866 | .index = 0, |
| @@ -6869,7 +6869,7 @@ static struct snd_kcontrol_new volume_alsa_control_vol = { | |||
| 6869 | .get = volume_alsa_vol_get, | 6869 | .get = volume_alsa_vol_get, |
| 6870 | }; | 6870 | }; |
| 6871 | 6871 | ||
| 6872 | static struct snd_kcontrol_new volume_alsa_control_mute = { | 6872 | static struct snd_kcontrol_new volume_alsa_control_mute __initdata = { |
| 6873 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 6873 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 6874 | .name = "Console Playback Switch", | 6874 | .name = "Console Playback Switch", |
| 6875 | .index = 0, | 6875 | .index = 0, |
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 76441dcbe5ff..e4da61bcbf8b 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
| @@ -222,6 +222,12 @@ static const struct dmi_system_id toshiba_alt_keymap_dmi[] = { | |||
| 222 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), | 222 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), |
| 223 | }, | 223 | }, |
| 224 | }, | 224 | }, |
| 225 | { | ||
| 226 | .matches = { | ||
| 227 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
| 228 | DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"), | ||
| 229 | }, | ||
| 230 | }, | ||
| 225 | {} | 231 | {} |
| 226 | }; | 232 | }; |
| 227 | 233 | ||
| @@ -229,6 +235,7 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = { | |||
| 229 | { KE_KEY, 0x157, { KEY_MUTE } }, | 235 | { KE_KEY, 0x157, { KEY_MUTE } }, |
| 230 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, | 236 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, |
| 231 | { KE_KEY, 0x103, { KEY_ZOOMIN } }, | 237 | { KE_KEY, 0x103, { KEY_ZOOMIN } }, |
| 238 | { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } }, | ||
| 232 | { KE_KEY, 0x139, { KEY_ZOOMRESET } }, | 239 | { KE_KEY, 0x139, { KEY_ZOOMRESET } }, |
| 233 | { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, | 240 | { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, |
| 234 | { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, | 241 | { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, |
| @@ -872,7 +879,9 @@ static int lcd_proc_open(struct inode *inode, struct file *file) | |||
| 872 | 879 | ||
| 873 | static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) | 880 | static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) |
| 874 | { | 881 | { |
| 875 | u32 hci_result; | 882 | u32 in[HCI_WORDS] = { HCI_SET, HCI_LCD_BRIGHTNESS, 0, 0, 0, 0 }; |
| 883 | u32 out[HCI_WORDS]; | ||
| 884 | acpi_status status; | ||
| 876 | 885 | ||
| 877 | if (dev->tr_backlight_supported) { | 886 | if (dev->tr_backlight_supported) { |
| 878 | bool enable = !value; | 887 | bool enable = !value; |
| @@ -883,9 +892,20 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) | |||
| 883 | value--; | 892 | value--; |
| 884 | } | 893 | } |
| 885 | 894 | ||
| 886 | value = value << HCI_LCD_BRIGHTNESS_SHIFT; | 895 | in[2] = value << HCI_LCD_BRIGHTNESS_SHIFT; |
| 887 | hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); | 896 | status = hci_raw(dev, in, out); |
| 888 | return hci_result == HCI_SUCCESS ? 0 : -EIO; | 897 | if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) { |
| 898 | pr_err("ACPI call to set brightness failed"); | ||
| 899 | return -EIO; | ||
| 900 | } | ||
| 901 | /* Extra check for "incomplete" backlight method, where the AML code | ||
| 902 | * doesn't check for HCI_SET or HCI_GET and returns HCI_SUCCESS, | ||
| 903 | * the actual brightness, and in some cases the max brightness. | ||
| 904 | */ | ||
| 905 | if (out[2] > 0 || out[3] == 0xE000) | ||
| 906 | return -ENODEV; | ||
| 907 | |||
| 908 | return out[0] == HCI_SUCCESS ? 0 : -EIO; | ||
| 889 | } | 909 | } |
| 890 | 910 | ||
| 891 | static int set_lcd_status(struct backlight_device *bd) | 911 | static int set_lcd_status(struct backlight_device *bd) |
| @@ -1238,7 +1258,7 @@ static ssize_t toshiba_kbd_bl_mode_store(struct device *dev, | |||
| 1238 | int mode = -1; | 1258 | int mode = -1; |
| 1239 | int time = -1; | 1259 | int time = -1; |
| 1240 | 1260 | ||
| 1241 | if (sscanf(buf, "%i", &mode) != 1 && (mode != 2 || mode != 1)) | 1261 | if (sscanf(buf, "%i", &mode) != 1 || (mode != 2 || mode != 1)) |
| 1242 | return -EINVAL; | 1262 | return -EINVAL; |
| 1243 | 1263 | ||
| 1244 | /* Set the Keyboard Backlight Mode where: | 1264 | /* Set the Keyboard Backlight Mode where: |
diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c new file mode 100644 index 000000000000..65300b6a84b9 --- /dev/null +++ b/drivers/platform/x86/toshiba_haps.c | |||
| @@ -0,0 +1,265 @@ | |||
| 1 | /* | ||
| 2 | * Toshiba HDD Active Protection Sensor (HAPS) driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Azael Avalos <coproscefalo@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 as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 19 | |||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/types.h> | ||
| 24 | #include <linux/acpi.h> | ||
| 25 | |||
| 26 | MODULE_AUTHOR("Azael Avalos <coproscefalo@gmail.com>"); | ||
| 27 | MODULE_DESCRIPTION("Toshiba HDD Active Protection Sensor"); | ||
| 28 | MODULE_LICENSE("GPL"); | ||
| 29 | |||
| 30 | struct toshiba_haps_dev { | ||
| 31 | struct acpi_device *acpi_dev; | ||
| 32 | |||
| 33 | int protection_level; | ||
| 34 | }; | ||
| 35 | |||
| 36 | static struct toshiba_haps_dev *toshiba_haps; | ||
| 37 | |||
| 38 | /* HAPS functions */ | ||
| 39 | static int toshiba_haps_reset_protection(acpi_handle handle) | ||
| 40 | { | ||
| 41 | acpi_status status; | ||
| 42 | |||
| 43 | status = acpi_evaluate_object(handle, "RSSS", NULL, NULL); | ||
| 44 | if (ACPI_FAILURE(status)) { | ||
| 45 | pr_err("Unable to reset the HDD protection\n"); | ||
| 46 | return -EIO; | ||
| 47 | } | ||
| 48 | |||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static int toshiba_haps_protection_level(acpi_handle handle, int level) | ||
| 53 | { | ||
| 54 | acpi_status status; | ||
| 55 | |||
| 56 | status = acpi_execute_simple_method(handle, "PTLV", level); | ||
| 57 | if (ACPI_FAILURE(status)) { | ||
| 58 | pr_err("Error while setting the protection level\n"); | ||
| 59 | return -EIO; | ||
| 60 | } | ||
| 61 | |||
| 62 | pr_info("HDD protection level set to: %d\n", level); | ||
| 63 | |||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | /* sysfs files */ | ||
| 68 | static ssize_t protection_level_show(struct device *dev, | ||
| 69 | struct device_attribute *attr, char *buf) | ||
| 70 | { | ||
| 71 | struct toshiba_haps_dev *haps = dev_get_drvdata(dev); | ||
| 72 | |||
| 73 | return sprintf(buf, "%i\n", haps->protection_level); | ||
| 74 | } | ||
| 75 | |||
| 76 | static ssize_t protection_level_store(struct device *dev, | ||
| 77 | struct device_attribute *attr, | ||
| 78 | const char *buf, size_t count) | ||
| 79 | { | ||
| 80 | struct toshiba_haps_dev *haps = dev_get_drvdata(dev); | ||
| 81 | int level, ret; | ||
| 82 | |||
| 83 | if (sscanf(buf, "%d", &level) != 1 || level < 0 || level > 3) | ||
| 84 | return -EINVAL; | ||
| 85 | |||
| 86 | /* Set the sensor level. | ||
| 87 | * Acceptable levels are: | ||
| 88 | * 0 - Disabled | 1 - Low | 2 - Medium | 3 - High | ||
| 89 | */ | ||
| 90 | ret = toshiba_haps_protection_level(haps->acpi_dev->handle, level); | ||
| 91 | if (ret != 0) | ||
| 92 | return ret; | ||
| 93 | |||
| 94 | haps->protection_level = level; | ||
| 95 | |||
| 96 | return count; | ||
| 97 | } | ||
| 98 | |||
| 99 | static ssize_t reset_protection_store(struct device *dev, | ||
| 100 | struct device_attribute *attr, | ||
| 101 | const char *buf, size_t count) | ||
| 102 | { | ||
| 103 | struct toshiba_haps_dev *haps = dev_get_drvdata(dev); | ||
| 104 | int reset, ret; | ||
| 105 | |||
| 106 | if (sscanf(buf, "%d", &reset) != 1 || reset != 1) | ||
| 107 | return -EINVAL; | ||
| 108 | |||
| 109 | /* Reset the protection interface */ | ||
| 110 | ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); | ||
| 111 | if (ret != 0) | ||
| 112 | return ret; | ||
| 113 | |||
| 114 | return count; | ||
| 115 | } | ||
| 116 | |||
| 117 | static DEVICE_ATTR(protection_level, S_IRUGO | S_IWUSR, | ||
| 118 | protection_level_show, protection_level_store); | ||
| 119 | static DEVICE_ATTR(reset_protection, S_IWUSR, NULL, reset_protection_store); | ||
| 120 | |||
| 121 | static struct attribute *haps_attributes[] = { | ||
| 122 | &dev_attr_protection_level.attr, | ||
| 123 | &dev_attr_reset_protection.attr, | ||
| 124 | NULL, | ||
| 125 | }; | ||
| 126 | |||
| 127 | static struct attribute_group haps_attr_group = { | ||
| 128 | .attrs = haps_attributes, | ||
| 129 | }; | ||
| 130 | |||
| 131 | /* | ||
| 132 | * ACPI stuff | ||
| 133 | */ | ||
| 134 | static void toshiba_haps_notify(struct acpi_device *device, u32 event) | ||
| 135 | { | ||
| 136 | pr_info("Received event: 0x%x", event); | ||
| 137 | |||
| 138 | acpi_bus_generate_netlink_event(device->pnp.device_class, | ||
| 139 | dev_name(&device->dev), | ||
| 140 | event, 0); | ||
| 141 | } | ||
| 142 | |||
| 143 | static int toshiba_haps_remove(struct acpi_device *device) | ||
| 144 | { | ||
| 145 | sysfs_remove_group(&device->dev.kobj, &haps_attr_group); | ||
| 146 | |||
| 147 | if (toshiba_haps) | ||
| 148 | toshiba_haps = NULL; | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* Helper function */ | ||
| 154 | static int toshiba_haps_available(acpi_handle handle) | ||
| 155 | { | ||
| 156 | acpi_status status; | ||
| 157 | u64 hdd_present; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * A non existent device as well as having (only) | ||
| 161 | * Solid State Drives can cause the call to fail. | ||
| 162 | */ | ||
| 163 | status = acpi_evaluate_integer(handle, "_STA", NULL, | ||
| 164 | &hdd_present); | ||
| 165 | if (ACPI_FAILURE(status) || !hdd_present) { | ||
| 166 | pr_info("HDD protection not available or using SSD\n"); | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | return 1; | ||
| 171 | } | ||
| 172 | |||
| 173 | static int toshiba_haps_add(struct acpi_device *acpi_dev) | ||
| 174 | { | ||
| 175 | struct toshiba_haps_dev *haps; | ||
| 176 | int ret; | ||
| 177 | |||
| 178 | if (toshiba_haps) | ||
| 179 | return -EBUSY; | ||
| 180 | |||
| 181 | if (!toshiba_haps_available(acpi_dev->handle)) | ||
| 182 | return -ENODEV; | ||
| 183 | |||
| 184 | pr_info("Toshiba HDD Active Protection Sensor device\n"); | ||
| 185 | |||
| 186 | haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL); | ||
| 187 | if (!haps) | ||
| 188 | return -ENOMEM; | ||
| 189 | |||
| 190 | haps->acpi_dev = acpi_dev; | ||
| 191 | haps->protection_level = 2; | ||
| 192 | acpi_dev->driver_data = haps; | ||
| 193 | dev_set_drvdata(&acpi_dev->dev, haps); | ||
| 194 | |||
| 195 | /* Set the protection level, currently at level 2 (Medium) */ | ||
| 196 | ret = toshiba_haps_protection_level(acpi_dev->handle, 2); | ||
| 197 | if (ret != 0) | ||
| 198 | return ret; | ||
| 199 | |||
| 200 | ret = sysfs_create_group(&acpi_dev->dev.kobj, &haps_attr_group); | ||
| 201 | if (ret) | ||
| 202 | return ret; | ||
| 203 | |||
| 204 | toshiba_haps = haps; | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | #ifdef CONFIG_PM_SLEEP | ||
| 210 | static int toshiba_haps_suspend(struct device *device) | ||
| 211 | { | ||
| 212 | struct toshiba_haps_dev *haps; | ||
| 213 | int ret; | ||
| 214 | |||
| 215 | haps = acpi_driver_data(to_acpi_device(device)); | ||
| 216 | |||
| 217 | /* Deactivate the protection on suspend */ | ||
| 218 | ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 0); | ||
| 219 | |||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int toshiba_haps_resume(struct device *device) | ||
| 224 | { | ||
| 225 | struct toshiba_haps_dev *haps; | ||
| 226 | int ret; | ||
| 227 | |||
| 228 | haps = acpi_driver_data(to_acpi_device(device)); | ||
| 229 | |||
| 230 | /* Set the stored protection level */ | ||
| 231 | ret = toshiba_haps_protection_level(haps->acpi_dev->handle, | ||
| 232 | haps->protection_level); | ||
| 233 | |||
| 234 | /* Reset the protection on resume */ | ||
| 235 | ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); | ||
| 236 | if (ret != 0) | ||
| 237 | return ret; | ||
| 238 | |||
| 239 | return ret; | ||
| 240 | } | ||
| 241 | #endif | ||
| 242 | |||
| 243 | static SIMPLE_DEV_PM_OPS(toshiba_haps_pm, | ||
| 244 | toshiba_haps_suspend, toshiba_haps_resume); | ||
| 245 | |||
| 246 | static const struct acpi_device_id haps_device_ids[] = { | ||
| 247 | {"TOS620A", 0}, | ||
| 248 | {"", 0}, | ||
| 249 | }; | ||
| 250 | MODULE_DEVICE_TABLE(acpi, haps_device_ids); | ||
| 251 | |||
| 252 | static struct acpi_driver toshiba_haps_driver = { | ||
| 253 | .name = "Toshiba HAPS", | ||
| 254 | .owner = THIS_MODULE, | ||
| 255 | .ids = haps_device_ids, | ||
| 256 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
| 257 | .ops = { | ||
| 258 | .add = toshiba_haps_add, | ||
| 259 | .remove = toshiba_haps_remove, | ||
| 260 | .notify = toshiba_haps_notify, | ||
| 261 | }, | ||
| 262 | .drv.pm = &toshiba_haps_pm, | ||
| 263 | }; | ||
| 264 | |||
| 265 | module_acpi_driver(toshiba_haps_driver); | ||
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 43d13295e63d..737e56d46f61 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c | |||
| @@ -256,10 +256,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) | |||
| 256 | block = &wblock->gblock; | 256 | block = &wblock->gblock; |
| 257 | handle = wblock->handle; | 257 | handle = wblock->handle; |
| 258 | 258 | ||
| 259 | if (!block) | ||
| 260 | return AE_NOT_EXIST; | ||
| 261 | |||
| 262 | |||
| 263 | snprintf(method, 5, "WE%02X", block->notify_id); | 259 | snprintf(method, 5, "WE%02X", block->notify_id); |
| 264 | status = acpi_execute_simple_method(handle, method, enable); | 260 | status = acpi_execute_simple_method(handle, method, enable); |
| 265 | 261 | ||
