diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-26 16:44:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-26 16:44:46 -0400 |
commit | 78d425677217b655ed36c492a070b5002832fc73 (patch) | |
tree | a178a3bf773027f3a70ecec1ad6f9d35074e4263 | |
parent | 36a8032d77649430f5ef11fbf0df2bb026be0b04 (diff) | |
parent | 358d6a2c3ecae2b22c7d7e61f9d5672557446dfb (diff) |
Merge tag 'platform-drivers-x86-v4.1-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86
Pull x86 platform driver updates from Darren Hart:
"This series includes significant updates to the toshiba_acpi driver
and the reintroduction of the dell-laptop keyboard backlight additions
I had to revert previously. Also included are various fixes for
typos, warnings, correctness, and minor bugs.
Specifics:
dell-laptop:
- add support for keyboard backlight.
toshiba_acpi:
- adaptive keyboard, hotkey, USB sleep and charge, and backlight
updates. Update sysfs documentation.
toshiba_bluetooth:
- fix enabling/disabling loop on recent devices
apple-gmux:
- lock iGP IO to protect from vgaarb changes
other:
- Fix typos, clear gcc warnings, clarify pr_* messages, correct
return types, update MAINTAINERS"
* tag 'platform-drivers-x86-v4.1-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86: (25 commits)
toshiba_acpi: Do not register vendor backlight when acpi_video bl is available
MAINTAINERS: Add me on list of Dell laptop drivers
platform: x86: dell-laptop: Add support for keyboard backlight
Documentation/ABI: Update sysfs-driver-toshiba_acpi entry
toshiba_acpi: Fix pr_* messages from USB Sleep Functions
toshiba_acpi: Update and fix USB Sleep and Charge modes
wmi: Use bool function return values of true/false not 1/0
toshiba_bluetooth: Fix enabling/disabling loop on recent devices
toshiba_bluetooth: Clean up *_add function and disable BT device at removal
toshiba_bluetooth: Add three new functions to the driver
toshiba_acpi: Fix the enabling of the Special Functions
toshiba_acpi: Use the Hotkey Event Type function for keymap choosing
toshiba_acpi: Add Hotkey Event Type function and definitions
x86/wmi: delete unused wmi_data_lock mutex causing gcc warning
apple-gmux: lock iGP IO to protect from vgaarb changes
MAINTAINERS: Add missing Toshiba devices and add myself as maintainer
toshiba_acpi: Update events in toshiba_acpi_notify
intel-oaktrail: Fix trivial typo in comment
thinkpad_acpi: off by one in adaptive_keyboard_hotkey_notify_hotkey()
thinkpad_acpi: signedness bugs getting current_mode
...
-rw-r--r-- | Documentation/ABI/testing/sysfs-driver-toshiba_acpi | 93 | ||||
-rw-r--r-- | Documentation/ABI/testing/sysfs-platform-dell-laptop | 69 | ||||
-rw-r--r-- | Documentation/laptops/thinkpad-acpi.txt | 18 | ||||
-rw-r--r-- | MAINTAINERS | 22 | ||||
-rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/x86/apple-gmux.c | 48 | ||||
-rw-r--r-- | drivers/platform/x86/dell-laptop.c | 1089 | ||||
-rw-r--r-- | drivers/platform/x86/intel_oaktrail.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 320 | ||||
-rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 256 | ||||
-rw-r--r-- | drivers/platform/x86/toshiba_bluetooth.c | 133 | ||||
-rw-r--r-- | drivers/platform/x86/wmi.c | 5 |
12 files changed, 1838 insertions, 218 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-toshiba_acpi b/Documentation/ABI/testing/sysfs-driver-toshiba_acpi index ca9c71a531c5..eed922ef42e5 100644 --- a/Documentation/ABI/testing/sysfs-driver-toshiba_acpi +++ b/Documentation/ABI/testing/sysfs-driver-toshiba_acpi | |||
@@ -8,9 +8,11 @@ Description: This file controls the keyboard backlight operation mode, valid | |||
8 | * 0x2 -> AUTO (also called TIMER) | 8 | * 0x2 -> AUTO (also called TIMER) |
9 | * 0x8 -> ON | 9 | * 0x8 -> ON |
10 | * 0x10 -> OFF | 10 | * 0x10 -> OFF |
11 | Note that the kernel 3.16 onwards this file accepts all listed | 11 | Note that from kernel 3.16 onwards this file accepts all listed |
12 | parameters, kernel 3.15 only accepts the first two (FN-Z and | 12 | parameters, kernel 3.15 only accepts the first two (FN-Z and |
13 | AUTO). | 13 | AUTO). |
14 | Also note that toggling this value on type 1 devices, requires | ||
15 | a reboot for changes to take effect. | ||
14 | Users: KToshiba | 16 | Users: KToshiba |
15 | 17 | ||
16 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_backlight_timeout | 18 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_backlight_timeout |
@@ -67,15 +69,72 @@ Description: This file shows the current keyboard backlight type, | |||
67 | * 2 -> Type 2, supporting modes TIMER, ON and OFF | 69 | * 2 -> Type 2, supporting modes TIMER, ON and OFF |
68 | Users: KToshiba | 70 | Users: KToshiba |
69 | 71 | ||
72 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_sleep_charge | ||
73 | Date: January 23, 2015 | ||
74 | KernelVersion: 4.0 | ||
75 | Contact: Azael Avalos <coproscefalo@gmail.com> | ||
76 | Description: This file controls the USB Sleep & Charge charging mode, which | ||
77 | can be: | ||
78 | * 0 -> Disabled (0x00) | ||
79 | * 1 -> Alternate (0x09) | ||
80 | * 2 -> Auto (0x21) | ||
81 | * 3 -> Typical (0x11) | ||
82 | Note that from kernel 4.1 onwards this file accepts all listed | ||
83 | values, kernel 4.0 only supports the first three. | ||
84 | Note that this feature only works when connected to power, if | ||
85 | you want to use it under battery, see the entry named | ||
86 | "sleep_functions_on_battery" | ||
87 | Users: KToshiba | ||
88 | |||
89 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/sleep_functions_on_battery | ||
90 | Date: January 23, 2015 | ||
91 | KernelVersion: 4.0 | ||
92 | Contact: Azael Avalos <coproscefalo@gmail.com> | ||
93 | Description: This file controls the USB Sleep Functions under battery, and | ||
94 | set the level at which point they will be disabled, accepted | ||
95 | values can be: | ||
96 | * 0 -> Disabled | ||
97 | * 1-100 -> Battery level to disable sleep functions | ||
98 | Currently it prints two values, the first one indicates if the | ||
99 | feature is enabled or disabled, while the second one shows the | ||
100 | current battery level set. | ||
101 | Note that when the value is set to disabled, the sleep function | ||
102 | will only work when connected to power. | ||
103 | Users: KToshiba | ||
104 | |||
105 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_rapid_charge | ||
106 | Date: January 23, 2015 | ||
107 | KernelVersion: 4.0 | ||
108 | Contact: Azael Avalos <coproscefalo@gmail.com> | ||
109 | Description: This file controls the USB Rapid Charge state, which can be: | ||
110 | * 0 -> Disabled | ||
111 | * 1 -> Enabled | ||
112 | Note that toggling this value requires a reboot for changes to | ||
113 | take effect. | ||
114 | Users: KToshiba | ||
115 | |||
116 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_sleep_music | ||
117 | Date: January 23, 2015 | ||
118 | KernelVersion: 4.0 | ||
119 | Contact: Azael Avalos <coproscefalo@gmail.com> | ||
120 | Description: This file controls the Sleep & Music state, which values can be: | ||
121 | * 0 -> Disabled | ||
122 | * 1 -> Enabled | ||
123 | Note that this feature only works when connected to power, if | ||
124 | you want to use it under battery, see the entry named | ||
125 | "sleep_functions_on_battery" | ||
126 | Users: KToshiba | ||
127 | |||
70 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/version | 128 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/version |
71 | Date: February, 2015 | 129 | Date: February 12, 2015 |
72 | KernelVersion: 3.20 | 130 | KernelVersion: 4.0 |
73 | Contact: Azael Avalos <coproscefalo@gmail.com> | 131 | Contact: Azael Avalos <coproscefalo@gmail.com> |
74 | Description: This file shows the current version of the driver | 132 | Description: This file shows the current version of the driver |
133 | Users: KToshiba | ||
75 | 134 | ||
76 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/fan | 135 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/fan |
77 | Date: February, 2015 | 136 | Date: February 12, 2015 |
78 | KernelVersion: 3.20 | 137 | KernelVersion: 4.0 |
79 | Contact: Azael Avalos <coproscefalo@gmail.com> | 138 | Contact: Azael Avalos <coproscefalo@gmail.com> |
80 | Description: This file controls the state of the internal fan, valid | 139 | Description: This file controls the state of the internal fan, valid |
81 | values are: | 140 | values are: |
@@ -83,8 +142,8 @@ Description: This file controls the state of the internal fan, valid | |||
83 | * 1 -> ON | 142 | * 1 -> ON |
84 | 143 | ||
85 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_function_keys | 144 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_function_keys |
86 | Date: February, 2015 | 145 | Date: February 12, 2015 |
87 | KernelVersion: 3.20 | 146 | KernelVersion: 4.0 |
88 | Contact: Azael Avalos <coproscefalo@gmail.com> | 147 | Contact: Azael Avalos <coproscefalo@gmail.com> |
89 | Description: This file controls the Special Functions (hotkeys) operation | 148 | Description: This file controls the Special Functions (hotkeys) operation |
90 | mode, valid values are: | 149 | mode, valid values are: |
@@ -94,21 +153,29 @@ Description: This file controls the Special Functions (hotkeys) operation | |||
94 | and the hotkeys are accessed via FN-F{1-12}. | 153 | and the hotkeys are accessed via FN-F{1-12}. |
95 | In the "Special Functions" mode, the F{1-12} keys trigger the | 154 | In the "Special Functions" mode, the F{1-12} keys trigger the |
96 | hotkey and the F{1-12} keys are accessed via FN-F{1-12}. | 155 | hotkey and the F{1-12} keys are accessed via FN-F{1-12}. |
156 | Note that toggling this value requires a reboot for changes to | ||
157 | take effect. | ||
158 | Users: KToshiba | ||
97 | 159 | ||
98 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/panel_power_on | 160 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/panel_power_on |
99 | Date: February, 2015 | 161 | Date: February 12, 2015 |
100 | KernelVersion: 3.20 | 162 | KernelVersion: 4.0 |
101 | Contact: Azael Avalos <coproscefalo@gmail.com> | 163 | Contact: Azael Avalos <coproscefalo@gmail.com> |
102 | Description: This file controls whether the laptop should turn ON whenever | 164 | Description: This file controls whether the laptop should turn ON whenever |
103 | the LID is opened, valid values are: | 165 | the LID is opened, valid values are: |
104 | * 0 -> Disabled | 166 | * 0 -> Disabled |
105 | * 1 -> Enabled | 167 | * 1 -> Enabled |
168 | Note that toggling this value requires a reboot for changes to | ||
169 | take effect. | ||
170 | Users: KToshiba | ||
106 | 171 | ||
107 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_three | 172 | What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_three |
108 | Date: February, 2015 | 173 | Date: February 12, 2015 |
109 | KernelVersion: 3.20 | 174 | KernelVersion: 4.0 |
110 | Contact: Azael Avalos <coproscefalo@gmail.com> | 175 | Contact: Azael Avalos <coproscefalo@gmail.com> |
111 | Description: This file controls whether the USB 3 functionality, valid | 176 | Description: This file controls the USB 3 functionality, valid values are: |
112 | values are: | ||
113 | * 0 -> Disabled (Acts as a regular USB 2) | 177 | * 0 -> Disabled (Acts as a regular USB 2) |
114 | * 1 -> Enabled (Full USB 3 functionality) | 178 | * 1 -> Enabled (Full USB 3 functionality) |
179 | Note that toggling this value requires a reboot for changes to | ||
180 | take effect. | ||
181 | Users: KToshiba | ||
diff --git a/Documentation/ABI/testing/sysfs-platform-dell-laptop b/Documentation/ABI/testing/sysfs-platform-dell-laptop new file mode 100644 index 000000000000..8c6a0b8e1131 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-dell-laptop | |||
@@ -0,0 +1,69 @@ | |||
1 | What: /sys/class/leds/dell::kbd_backlight/als_enabled | ||
2 | Date: December 2014 | ||
3 | KernelVersion: 3.19 | ||
4 | Contact: Gabriele Mazzotta <gabriele.mzt@gmail.com>, | ||
5 | Pali Rohár <pali.rohar@gmail.com> | ||
6 | Description: | ||
7 | This file allows to control the automatic keyboard | ||
8 | illumination mode on some systems that have an ambient | ||
9 | light sensor. Write 1 to this file to enable the auto | ||
10 | mode, 0 to disable it. | ||
11 | |||
12 | What: /sys/class/leds/dell::kbd_backlight/als_setting | ||
13 | Date: December 2014 | ||
14 | KernelVersion: 3.19 | ||
15 | Contact: Gabriele Mazzotta <gabriele.mzt@gmail.com>, | ||
16 | Pali Rohár <pali.rohar@gmail.com> | ||
17 | Description: | ||
18 | This file allows to specifiy the on/off threshold value, | ||
19 | as reported by the ambient light sensor. | ||
20 | |||
21 | What: /sys/class/leds/dell::kbd_backlight/start_triggers | ||
22 | Date: December 2014 | ||
23 | KernelVersion: 3.19 | ||
24 | Contact: Gabriele Mazzotta <gabriele.mzt@gmail.com>, | ||
25 | Pali Rohár <pali.rohar@gmail.com> | ||
26 | Description: | ||
27 | This file allows to control the input triggers that | ||
28 | turn on the keyboard backlight illumination that is | ||
29 | disabled because of inactivity. | ||
30 | Read the file to see the triggers available. The ones | ||
31 | enabled are preceded by '+', those disabled by '-'. | ||
32 | |||
33 | To enable a trigger, write its name preceded by '+' to | ||
34 | this file. To disable a trigger, write its name preceded | ||
35 | by '-' instead. | ||
36 | |||
37 | For example, to enable the keyboard as trigger run: | ||
38 | echo +keyboard > /sys/class/leds/dell::kbd_backlight/start_triggers | ||
39 | To disable it: | ||
40 | echo -keyboard > /sys/class/leds/dell::kbd_backlight/start_triggers | ||
41 | |||
42 | Note that not all the available triggers can be configured. | ||
43 | |||
44 | What: /sys/class/leds/dell::kbd_backlight/stop_timeout | ||
45 | Date: December 2014 | ||
46 | KernelVersion: 3.19 | ||
47 | Contact: Gabriele Mazzotta <gabriele.mzt@gmail.com>, | ||
48 | Pali Rohár <pali.rohar@gmail.com> | ||
49 | Description: | ||
50 | This file allows to specify the interval after which the | ||
51 | keyboard illumination is disabled because of inactivity. | ||
52 | The timeouts are expressed in seconds, minutes, hours and | ||
53 | days, for which the symbols are 's', 'm', 'h' and 'd' | ||
54 | respectively. | ||
55 | |||
56 | To configure the timeout, write to this file a value along | ||
57 | with any the above units. If no unit is specified, the value | ||
58 | is assumed to be expressed in seconds. | ||
59 | |||
60 | For example, to set the timeout to 10 minutes run: | ||
61 | echo 10m > /sys/class/leds/dell::kbd_backlight/stop_timeout | ||
62 | |||
63 | Note that when this file is read, the returned value might be | ||
64 | expressed in a different unit than the one used when the timeout | ||
65 | was set. | ||
66 | |||
67 | Also note that only some timeouts are supported and that | ||
68 | some systems might fall back to a specific timeout in case | ||
69 | an invalid timeout is written to this file. | ||
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index fc04c14de4bb..72a150d8f3df 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt | |||
@@ -1355,6 +1355,24 @@ Sysfs notes: | |||
1355 | rfkill controller switch "tpacpi_uwb_sw": refer to | 1355 | rfkill controller switch "tpacpi_uwb_sw": refer to |
1356 | Documentation/rfkill.txt for details. | 1356 | Documentation/rfkill.txt for details. |
1357 | 1357 | ||
1358 | Adaptive keyboard | ||
1359 | ----------------- | ||
1360 | |||
1361 | sysfs device attribute: adaptive_kbd_mode | ||
1362 | |||
1363 | This sysfs attribute controls the keyboard "face" that will be shown on the | ||
1364 | Lenovo X1 Carbon 2nd gen (2014)'s adaptive keyboard. The value can be read | ||
1365 | and set. | ||
1366 | |||
1367 | 1 = Home mode | ||
1368 | 2 = Web-browser mode | ||
1369 | 3 = Web-conference mode | ||
1370 | 4 = Function mode | ||
1371 | 5 = Layflat mode | ||
1372 | |||
1373 | For more details about which buttons will appear depending on the mode, please | ||
1374 | review the laptop's user guide: | ||
1375 | http://www.lenovo.com/shop/americas/content/user_guides/x1carbon_2_ug_en.pdf | ||
1358 | 1376 | ||
1359 | Multiple Commands, Module Parameters | 1377 | Multiple Commands, Module Parameters |
1360 | ------------------------------------ | 1378 | ------------------------------------ |
diff --git a/MAINTAINERS b/MAINTAINERS index 62cd43e7f56f..2b38266d592a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3066,10 +3066,16 @@ F: drivers/net/fddi/defxx.* | |||
3066 | 3066 | ||
3067 | DELL LAPTOP DRIVER | 3067 | DELL LAPTOP DRIVER |
3068 | M: Matthew Garrett <mjg59@srcf.ucam.org> | 3068 | M: Matthew Garrett <mjg59@srcf.ucam.org> |
3069 | M: Pali Rohár <pali.rohar@gmail.com> | ||
3069 | L: platform-driver-x86@vger.kernel.org | 3070 | L: platform-driver-x86@vger.kernel.org |
3070 | S: Maintained | 3071 | S: Maintained |
3071 | F: drivers/platform/x86/dell-laptop.c | 3072 | F: drivers/platform/x86/dell-laptop.c |
3072 | 3073 | ||
3074 | DELL LAPTOP FREEFALL DRIVER | ||
3075 | M: Pali Rohár <pali.rohar@gmail.com> | ||
3076 | S: Maintained | ||
3077 | F: drivers/platform/x86/dell-smo8800.c | ||
3078 | |||
3073 | DELL LAPTOP SMM DRIVER | 3079 | DELL LAPTOP SMM DRIVER |
3074 | M: Guenter Roeck <linux@roeck-us.net> | 3080 | M: Guenter Roeck <linux@roeck-us.net> |
3075 | S: Maintained | 3081 | S: Maintained |
@@ -3084,6 +3090,7 @@ F: drivers/firmware/dcdbas.* | |||
3084 | 3090 | ||
3085 | DELL WMI EXTRAS DRIVER | 3091 | DELL WMI EXTRAS DRIVER |
3086 | M: Matthew Garrett <mjg59@srcf.ucam.org> | 3092 | M: Matthew Garrett <mjg59@srcf.ucam.org> |
3093 | M: Pali Rohár <pali.rohar@gmail.com> | ||
3087 | S: Maintained | 3094 | S: Maintained |
3088 | F: drivers/platform/x86/dell-wmi.c | 3095 | F: drivers/platform/x86/dell-wmi.c |
3089 | 3096 | ||
@@ -9949,10 +9956,23 @@ S: Maintained | |||
9949 | F: drivers/platform/x86/topstar-laptop.c | 9956 | F: drivers/platform/x86/topstar-laptop.c |
9950 | 9957 | ||
9951 | TOSHIBA ACPI EXTRAS DRIVER | 9958 | TOSHIBA ACPI EXTRAS DRIVER |
9959 | M: Azael Avalos <coproscefalo@gmail.com> | ||
9952 | L: platform-driver-x86@vger.kernel.org | 9960 | L: platform-driver-x86@vger.kernel.org |
9953 | S: Orphan | 9961 | S: Maintained |
9954 | F: drivers/platform/x86/toshiba_acpi.c | 9962 | F: drivers/platform/x86/toshiba_acpi.c |
9955 | 9963 | ||
9964 | TOSHIBA BLUETOOTH DRIVER | ||
9965 | M: Azael Avalos <coproscefalo@gmail.com> | ||
9966 | L: platform-driver-x86@vger.kernel.org | ||
9967 | S: Maintained | ||
9968 | F: drivers/platform/x86/toshiba_bluetooth.c | ||
9969 | |||
9970 | TOSHIBA HDD ACTIVE PROTECTION SENSOR DRIVER | ||
9971 | M: Azael Avalos <coproscefalo@gmail.com> | ||
9972 | L: platform-driver-x86@vger.kernel.org | ||
9973 | S: Maintained | ||
9974 | F: drivers/platform/x86/toshiba_haps.c | ||
9975 | |||
9956 | TOSHIBA SMM DRIVER | 9976 | TOSHIBA SMM DRIVER |
9957 | M: Jonathan Buzzard <jonathan@buzzard.org.uk> | 9977 | M: Jonathan Buzzard <jonathan@buzzard.org.uk> |
9958 | L: tlinux-users@tce.toshiba-dme.co.jp | 9978 | L: tlinux-users@tce.toshiba-dme.co.jp |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 97527614141b..f9f205cb1f11 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -614,6 +614,7 @@ config ACPI_TOSHIBA | |||
614 | depends on INPUT | 614 | depends on INPUT |
615 | depends on RFKILL || RFKILL = n | 615 | depends on RFKILL || RFKILL = n |
616 | depends on SERIO_I8042 || SERIO_I8042 = n | 616 | depends on SERIO_I8042 || SERIO_I8042 = n |
617 | depends on ACPI_VIDEO || ACPI_VIDEO = n | ||
617 | select INPUT_POLLDEV | 618 | select INPUT_POLLDEV |
618 | select INPUT_SPARSEKMAP | 619 | select INPUT_SPARSEKMAP |
619 | ---help--- | 620 | ---help--- |
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 66d6d22c239c..6808715003f6 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/vga_switcheroo.h> | 24 | #include <linux/vga_switcheroo.h> |
25 | #include <linux/vgaarb.h> | ||
25 | #include <acpi/video.h> | 26 | #include <acpi/video.h> |
26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
27 | 28 | ||
@@ -31,6 +32,7 @@ struct apple_gmux_data { | |||
31 | bool indexed; | 32 | bool indexed; |
32 | struct mutex index_lock; | 33 | struct mutex index_lock; |
33 | 34 | ||
35 | struct pci_dev *pdev; | ||
34 | struct backlight_device *bdev; | 36 | struct backlight_device *bdev; |
35 | 37 | ||
36 | /* switcheroo data */ | 38 | /* switcheroo data */ |
@@ -415,6 +417,23 @@ static int gmux_resume(struct device *dev) | |||
415 | return 0; | 417 | return 0; |
416 | } | 418 | } |
417 | 419 | ||
420 | static struct pci_dev *gmux_get_io_pdev(void) | ||
421 | { | ||
422 | struct pci_dev *pdev = NULL; | ||
423 | |||
424 | while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev))) { | ||
425 | u16 cmd; | ||
426 | |||
427 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); | ||
428 | if (!(cmd & PCI_COMMAND_IO)) | ||
429 | continue; | ||
430 | |||
431 | return pdev; | ||
432 | } | ||
433 | |||
434 | return NULL; | ||
435 | } | ||
436 | |||
418 | static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | 437 | static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) |
419 | { | 438 | { |
420 | struct apple_gmux_data *gmux_data; | 439 | struct apple_gmux_data *gmux_data; |
@@ -425,6 +444,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | |||
425 | int ret = -ENXIO; | 444 | int ret = -ENXIO; |
426 | acpi_status status; | 445 | acpi_status status; |
427 | unsigned long long gpe; | 446 | unsigned long long gpe; |
447 | struct pci_dev *pdev = NULL; | ||
428 | 448 | ||
429 | if (apple_gmux_data) | 449 | if (apple_gmux_data) |
430 | return -EBUSY; | 450 | return -EBUSY; |
@@ -475,7 +495,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | |||
475 | ver_minor = (version >> 16) & 0xff; | 495 | ver_minor = (version >> 16) & 0xff; |
476 | ver_release = (version >> 8) & 0xff; | 496 | ver_release = (version >> 8) & 0xff; |
477 | } else { | 497 | } else { |
478 | pr_info("gmux device not present\n"); | 498 | pr_info("gmux device not present or IO disabled\n"); |
479 | ret = -ENODEV; | 499 | ret = -ENODEV; |
480 | goto err_release; | 500 | goto err_release; |
481 | } | 501 | } |
@@ -483,6 +503,23 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | |||
483 | pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, | 503 | pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, |
484 | ver_release, (gmux_data->indexed ? "indexed" : "classic")); | 504 | ver_release, (gmux_data->indexed ? "indexed" : "classic")); |
485 | 505 | ||
506 | /* | ||
507 | * Apple systems with gmux are EFI based and normally don't use | ||
508 | * VGA. In addition changing IO+MEM ownership between IGP and dGPU | ||
509 | * disables IO/MEM used for backlight control on some systems. | ||
510 | * Lock IO+MEM to GPU with active IO to prevent switch. | ||
511 | */ | ||
512 | pdev = gmux_get_io_pdev(); | ||
513 | if (pdev && vga_tryget(pdev, | ||
514 | VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM)) { | ||
515 | pr_err("IO+MEM vgaarb-locking for PCI:%s failed\n", | ||
516 | pci_name(pdev)); | ||
517 | ret = -EBUSY; | ||
518 | goto err_release; | ||
519 | } else if (pdev) | ||
520 | pr_info("locked IO for PCI:%s\n", pci_name(pdev)); | ||
521 | gmux_data->pdev = pdev; | ||
522 | |||
486 | memset(&props, 0, sizeof(props)); | 523 | memset(&props, 0, sizeof(props)); |
487 | props.type = BACKLIGHT_PLATFORM; | 524 | props.type = BACKLIGHT_PLATFORM; |
488 | props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); | 525 | props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); |
@@ -574,6 +611,10 @@ err_enable_gpe: | |||
574 | err_notify: | 611 | err_notify: |
575 | backlight_device_unregister(bdev); | 612 | backlight_device_unregister(bdev); |
576 | err_release: | 613 | err_release: |
614 | if (gmux_data->pdev) | ||
615 | vga_put(gmux_data->pdev, | ||
616 | VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM); | ||
617 | pci_dev_put(pdev); | ||
577 | release_region(gmux_data->iostart, gmux_data->iolen); | 618 | release_region(gmux_data->iostart, gmux_data->iolen); |
578 | err_free: | 619 | err_free: |
579 | kfree(gmux_data); | 620 | kfree(gmux_data); |
@@ -593,6 +634,11 @@ static void gmux_remove(struct pnp_dev *pnp) | |||
593 | &gmux_notify_handler); | 634 | &gmux_notify_handler); |
594 | } | 635 | } |
595 | 636 | ||
637 | if (gmux_data->pdev) { | ||
638 | vga_put(gmux_data->pdev, | ||
639 | VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM); | ||
640 | pci_dev_put(gmux_data->pdev); | ||
641 | } | ||
596 | backlight_device_unregister(gmux_data->bdev); | 642 | backlight_device_unregister(gmux_data->bdev); |
597 | 643 | ||
598 | release_region(gmux_data->iostart, gmux_data->iolen); | 644 | release_region(gmux_data->iostart, gmux_data->iolen); |
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 3d21efe11d7b..d688d806a8a5 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
@@ -2,9 +2,11 @@ | |||
2 | * Driver for Dell laptop extras | 2 | * Driver for Dell laptop extras |
3 | * | 3 | * |
4 | * Copyright (c) Red Hat <mjg@redhat.com> | 4 | * Copyright (c) Red Hat <mjg@redhat.com> |
5 | * Copyright (c) 2014 Gabriele Mazzotta <gabriele.mzt@gmail.com> | ||
6 | * Copyright (c) 2014 Pali Rohár <pali.rohar@gmail.com> | ||
5 | * | 7 | * |
6 | * Based on documentation in the libsmbios package, Copyright (C) 2005 Dell | 8 | * Based on documentation in the libsmbios package: |
7 | * Inc. | 9 | * Copyright (C) 2005-2014 Dell Inc. |
8 | * | 10 | * |
9 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -32,6 +34,13 @@ | |||
32 | #include "../../firmware/dcdbas.h" | 34 | #include "../../firmware/dcdbas.h" |
33 | 35 | ||
34 | #define BRIGHTNESS_TOKEN 0x7d | 36 | #define BRIGHTNESS_TOKEN 0x7d |
37 | #define KBD_LED_OFF_TOKEN 0x01E1 | ||
38 | #define KBD_LED_ON_TOKEN 0x01E2 | ||
39 | #define KBD_LED_AUTO_TOKEN 0x01E3 | ||
40 | #define KBD_LED_AUTO_25_TOKEN 0x02EA | ||
41 | #define KBD_LED_AUTO_50_TOKEN 0x02EB | ||
42 | #define KBD_LED_AUTO_75_TOKEN 0x02EC | ||
43 | #define KBD_LED_AUTO_100_TOKEN 0x02F6 | ||
35 | 44 | ||
36 | /* This structure will be modified by the firmware when we enter | 45 | /* This structure will be modified by the firmware when we enter |
37 | * system management mode, hence the volatiles */ | 46 | * system management mode, hence the volatiles */ |
@@ -62,6 +71,13 @@ struct calling_interface_structure { | |||
62 | 71 | ||
63 | struct quirk_entry { | 72 | struct quirk_entry { |
64 | u8 touchpad_led; | 73 | u8 touchpad_led; |
74 | |||
75 | int needs_kbd_timeouts; | ||
76 | /* | ||
77 | * Ordered list of timeouts expressed in seconds. | ||
78 | * The list must end with -1 | ||
79 | */ | ||
80 | int kbd_timeouts[]; | ||
65 | }; | 81 | }; |
66 | 82 | ||
67 | static struct quirk_entry *quirks; | 83 | static struct quirk_entry *quirks; |
@@ -76,6 +92,15 @@ static int __init dmi_matched(const struct dmi_system_id *dmi) | |||
76 | return 1; | 92 | return 1; |
77 | } | 93 | } |
78 | 94 | ||
95 | /* | ||
96 | * These values come from Windows utility provided by Dell. If any other value | ||
97 | * is used then BIOS silently set timeout to 0 without any error message. | ||
98 | */ | ||
99 | static struct quirk_entry quirk_dell_xps13_9333 = { | ||
100 | .needs_kbd_timeouts = 1, | ||
101 | .kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 }, | ||
102 | }; | ||
103 | |||
79 | static int da_command_address; | 104 | static int da_command_address; |
80 | static int da_command_code; | 105 | static int da_command_code; |
81 | static int da_num_tokens; | 106 | static int da_num_tokens; |
@@ -267,6 +292,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = { | |||
267 | }, | 292 | }, |
268 | .driver_data = &quirk_dell_vostro_v130, | 293 | .driver_data = &quirk_dell_vostro_v130, |
269 | }, | 294 | }, |
295 | { | ||
296 | .callback = dmi_matched, | ||
297 | .ident = "Dell XPS13 9333", | ||
298 | .matches = { | ||
299 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
300 | DMI_MATCH(DMI_PRODUCT_NAME, "XPS13 9333"), | ||
301 | }, | ||
302 | .driver_data = &quirk_dell_xps13_9333, | ||
303 | }, | ||
270 | { } | 304 | { } |
271 | }; | 305 | }; |
272 | 306 | ||
@@ -331,17 +365,29 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy) | |||
331 | } | 365 | } |
332 | } | 366 | } |
333 | 367 | ||
334 | static int find_token_location(int tokenid) | 368 | static int find_token_id(int tokenid) |
335 | { | 369 | { |
336 | int i; | 370 | int i; |
371 | |||
337 | for (i = 0; i < da_num_tokens; i++) { | 372 | for (i = 0; i < da_num_tokens; i++) { |
338 | if (da_tokens[i].tokenID == tokenid) | 373 | if (da_tokens[i].tokenID == tokenid) |
339 | return da_tokens[i].location; | 374 | return i; |
340 | } | 375 | } |
341 | 376 | ||
342 | return -1; | 377 | return -1; |
343 | } | 378 | } |
344 | 379 | ||
380 | static int find_token_location(int tokenid) | ||
381 | { | ||
382 | int id; | ||
383 | |||
384 | id = find_token_id(tokenid); | ||
385 | if (id == -1) | ||
386 | return -1; | ||
387 | |||
388 | return da_tokens[id].location; | ||
389 | } | ||
390 | |||
345 | static struct calling_interface_buffer * | 391 | static struct calling_interface_buffer * |
346 | dell_send_request(struct calling_interface_buffer *buffer, int class, | 392 | dell_send_request(struct calling_interface_buffer *buffer, int class, |
347 | int select) | 393 | int select) |
@@ -362,6 +408,20 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, | |||
362 | return buffer; | 408 | return buffer; |
363 | } | 409 | } |
364 | 410 | ||
411 | static inline int dell_smi_error(int value) | ||
412 | { | ||
413 | switch (value) { | ||
414 | case 0: /* Completed successfully */ | ||
415 | return 0; | ||
416 | case -1: /* Completed with error */ | ||
417 | return -EIO; | ||
418 | case -2: /* Function not supported */ | ||
419 | return -ENXIO; | ||
420 | default: /* Unknown error */ | ||
421 | return -EINVAL; | ||
422 | } | ||
423 | } | ||
424 | |||
365 | /* Derived from information in DellWirelessCtl.cpp: | 425 | /* Derived from information in DellWirelessCtl.cpp: |
366 | Class 17, select 11 is radio control. It returns an array of 32-bit values. | 426 | Class 17, select 11 is radio control. It returns an array of 32-bit values. |
367 | 427 | ||
@@ -716,7 +776,7 @@ static int dell_send_intensity(struct backlight_device *bd) | |||
716 | else | 776 | else |
717 | dell_send_request(buffer, 1, 1); | 777 | dell_send_request(buffer, 1, 1); |
718 | 778 | ||
719 | out: | 779 | out: |
720 | release_buffer(); | 780 | release_buffer(); |
721 | return ret; | 781 | return ret; |
722 | } | 782 | } |
@@ -740,7 +800,7 @@ static int dell_get_intensity(struct backlight_device *bd) | |||
740 | 800 | ||
741 | ret = buffer->output[1]; | 801 | ret = buffer->output[1]; |
742 | 802 | ||
743 | out: | 803 | out: |
744 | release_buffer(); | 804 | release_buffer(); |
745 | return ret; | 805 | return ret; |
746 | } | 806 | } |
@@ -789,6 +849,1018 @@ static void touchpad_led_exit(void) | |||
789 | led_classdev_unregister(&touchpad_led); | 849 | led_classdev_unregister(&touchpad_led); |
790 | } | 850 | } |
791 | 851 | ||
852 | /* | ||
853 | * Derived from information in smbios-keyboard-ctl: | ||
854 | * | ||
855 | * cbClass 4 | ||
856 | * cbSelect 11 | ||
857 | * Keyboard illumination | ||
858 | * cbArg1 determines the function to be performed | ||
859 | * | ||
860 | * cbArg1 0x0 = Get Feature Information | ||
861 | * cbRES1 Standard return codes (0, -1, -2) | ||
862 | * cbRES2, word0 Bitmap of user-selectable modes | ||
863 | * bit 0 Always off (All systems) | ||
864 | * bit 1 Always on (Travis ATG, Siberia) | ||
865 | * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG) | ||
866 | * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off | ||
867 | * bit 4 Auto: Input-activity-based On; input-activity based Off | ||
868 | * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off | ||
869 | * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off | ||
870 | * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off | ||
871 | * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off | ||
872 | * bits 9-15 Reserved for future use | ||
873 | * cbRES2, byte2 Reserved for future use | ||
874 | * cbRES2, byte3 Keyboard illumination type | ||
875 | * 0 Reserved | ||
876 | * 1 Tasklight | ||
877 | * 2 Backlight | ||
878 | * 3-255 Reserved for future use | ||
879 | * cbRES3, byte0 Supported auto keyboard illumination trigger bitmap. | ||
880 | * bit 0 Any keystroke | ||
881 | * bit 1 Touchpad activity | ||
882 | * bit 2 Pointing stick | ||
883 | * bit 3 Any mouse | ||
884 | * bits 4-7 Reserved for future use | ||
885 | * cbRES3, byte1 Supported timeout unit bitmap | ||
886 | * bit 0 Seconds | ||
887 | * bit 1 Minutes | ||
888 | * bit 2 Hours | ||
889 | * bit 3 Days | ||
890 | * bits 4-7 Reserved for future use | ||
891 | * cbRES3, byte2 Number of keyboard light brightness levels | ||
892 | * cbRES4, byte0 Maximum acceptable seconds value (0 if seconds not supported). | ||
893 | * cbRES4, byte1 Maximum acceptable minutes value (0 if minutes not supported). | ||
894 | * cbRES4, byte2 Maximum acceptable hours value (0 if hours not supported). | ||
895 | * cbRES4, byte3 Maximum acceptable days value (0 if days not supported) | ||
896 | * | ||
897 | * cbArg1 0x1 = Get Current State | ||
898 | * cbRES1 Standard return codes (0, -1, -2) | ||
899 | * cbRES2, word0 Bitmap of current mode state | ||
900 | * bit 0 Always off (All systems) | ||
901 | * bit 1 Always on (Travis ATG, Siberia) | ||
902 | * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG) | ||
903 | * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off | ||
904 | * bit 4 Auto: Input-activity-based On; input-activity based Off | ||
905 | * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off | ||
906 | * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off | ||
907 | * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off | ||
908 | * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off | ||
909 | * bits 9-15 Reserved for future use | ||
910 | * Note: Only One bit can be set | ||
911 | * cbRES2, byte2 Currently active auto keyboard illumination triggers. | ||
912 | * bit 0 Any keystroke | ||
913 | * bit 1 Touchpad activity | ||
914 | * bit 2 Pointing stick | ||
915 | * bit 3 Any mouse | ||
916 | * bits 4-7 Reserved for future use | ||
917 | * cbRES2, byte3 Current Timeout | ||
918 | * bits 7:6 Timeout units indicator: | ||
919 | * 00b Seconds | ||
920 | * 01b Minutes | ||
921 | * 10b Hours | ||
922 | * 11b Days | ||
923 | * bits 5:0 Timeout value (0-63) in sec/min/hr/day | ||
924 | * NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte | ||
925 | * are set upon return from the [Get feature information] call. | ||
926 | * cbRES3, byte0 Current setting of ALS value that turns the light on or off. | ||
927 | * cbRES3, byte1 Current ALS reading | ||
928 | * cbRES3, byte2 Current keyboard light level. | ||
929 | * | ||
930 | * cbArg1 0x2 = Set New State | ||
931 | * cbRES1 Standard return codes (0, -1, -2) | ||
932 | * cbArg2, word0 Bitmap of current mode state | ||
933 | * bit 0 Always off (All systems) | ||
934 | * bit 1 Always on (Travis ATG, Siberia) | ||
935 | * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG) | ||
936 | * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off | ||
937 | * bit 4 Auto: Input-activity-based On; input-activity based Off | ||
938 | * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off | ||
939 | * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off | ||
940 | * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off | ||
941 | * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off | ||
942 | * bits 9-15 Reserved for future use | ||
943 | * Note: Only One bit can be set | ||
944 | * cbArg2, byte2 Desired auto keyboard illumination triggers. Must remain inactive to allow | ||
945 | * keyboard to turn off automatically. | ||
946 | * bit 0 Any keystroke | ||
947 | * bit 1 Touchpad activity | ||
948 | * bit 2 Pointing stick | ||
949 | * bit 3 Any mouse | ||
950 | * bits 4-7 Reserved for future use | ||
951 | * cbArg2, byte3 Desired Timeout | ||
952 | * bits 7:6 Timeout units indicator: | ||
953 | * 00b Seconds | ||
954 | * 01b Minutes | ||
955 | * 10b Hours | ||
956 | * 11b Days | ||
957 | * bits 5:0 Timeout value (0-63) in sec/min/hr/day | ||
958 | * cbArg3, byte0 Desired setting of ALS value that turns the light on or off. | ||
959 | * cbArg3, byte2 Desired keyboard light level. | ||
960 | */ | ||
961 | |||
962 | |||
963 | enum kbd_timeout_unit { | ||
964 | KBD_TIMEOUT_SECONDS = 0, | ||
965 | KBD_TIMEOUT_MINUTES, | ||
966 | KBD_TIMEOUT_HOURS, | ||
967 | KBD_TIMEOUT_DAYS, | ||
968 | }; | ||
969 | |||
970 | enum kbd_mode_bit { | ||
971 | KBD_MODE_BIT_OFF = 0, | ||
972 | KBD_MODE_BIT_ON, | ||
973 | KBD_MODE_BIT_ALS, | ||
974 | KBD_MODE_BIT_TRIGGER_ALS, | ||
975 | KBD_MODE_BIT_TRIGGER, | ||
976 | KBD_MODE_BIT_TRIGGER_25, | ||
977 | KBD_MODE_BIT_TRIGGER_50, | ||
978 | KBD_MODE_BIT_TRIGGER_75, | ||
979 | KBD_MODE_BIT_TRIGGER_100, | ||
980 | }; | ||
981 | |||
982 | #define kbd_is_als_mode_bit(bit) \ | ||
983 | ((bit) == KBD_MODE_BIT_ALS || (bit) == KBD_MODE_BIT_TRIGGER_ALS) | ||
984 | #define kbd_is_trigger_mode_bit(bit) \ | ||
985 | ((bit) >= KBD_MODE_BIT_TRIGGER_ALS && (bit) <= KBD_MODE_BIT_TRIGGER_100) | ||
986 | #define kbd_is_level_mode_bit(bit) \ | ||
987 | ((bit) >= KBD_MODE_BIT_TRIGGER_25 && (bit) <= KBD_MODE_BIT_TRIGGER_100) | ||
988 | |||
989 | struct kbd_info { | ||
990 | u16 modes; | ||
991 | u8 type; | ||
992 | u8 triggers; | ||
993 | u8 levels; | ||
994 | u8 seconds; | ||
995 | u8 minutes; | ||
996 | u8 hours; | ||
997 | u8 days; | ||
998 | }; | ||
999 | |||
1000 | struct kbd_state { | ||
1001 | u8 mode_bit; | ||
1002 | u8 triggers; | ||
1003 | u8 timeout_value; | ||
1004 | u8 timeout_unit; | ||
1005 | u8 als_setting; | ||
1006 | u8 als_value; | ||
1007 | u8 level; | ||
1008 | }; | ||
1009 | |||
1010 | static const int kbd_tokens[] = { | ||
1011 | KBD_LED_OFF_TOKEN, | ||
1012 | KBD_LED_AUTO_25_TOKEN, | ||
1013 | KBD_LED_AUTO_50_TOKEN, | ||
1014 | KBD_LED_AUTO_75_TOKEN, | ||
1015 | KBD_LED_AUTO_100_TOKEN, | ||
1016 | KBD_LED_ON_TOKEN, | ||
1017 | }; | ||
1018 | |||
1019 | static u16 kbd_token_bits; | ||
1020 | |||
1021 | static struct kbd_info kbd_info; | ||
1022 | static bool kbd_als_supported; | ||
1023 | static bool kbd_triggers_supported; | ||
1024 | |||
1025 | static u8 kbd_mode_levels[16]; | ||
1026 | static int kbd_mode_levels_count; | ||
1027 | |||
1028 | static u8 kbd_previous_level; | ||
1029 | static u8 kbd_previous_mode_bit; | ||
1030 | |||
1031 | static bool kbd_led_present; | ||
1032 | |||
1033 | /* | ||
1034 | * NOTE: there are three ways to set the keyboard backlight level. | ||
1035 | * First, via kbd_state.mode_bit (assigning KBD_MODE_BIT_TRIGGER_* value). | ||
1036 | * Second, via kbd_state.level (assigning numerical value <= kbd_info.levels). | ||
1037 | * Third, via SMBIOS tokens (KBD_LED_* in kbd_tokens) | ||
1038 | * | ||
1039 | * There are laptops which support only one of these methods. If we want to | ||
1040 | * support as many machines as possible we need to implement all three methods. | ||
1041 | * The first two methods use the kbd_state structure. The third uses SMBIOS | ||
1042 | * tokens. If kbd_info.levels == 0, the machine does not support setting the | ||
1043 | * keyboard backlight level via kbd_state.level. | ||
1044 | */ | ||
1045 | |||
1046 | static int kbd_get_info(struct kbd_info *info) | ||
1047 | { | ||
1048 | u8 units; | ||
1049 | int ret; | ||
1050 | |||
1051 | get_buffer(); | ||
1052 | |||
1053 | buffer->input[0] = 0x0; | ||
1054 | dell_send_request(buffer, 4, 11); | ||
1055 | ret = buffer->output[0]; | ||
1056 | |||
1057 | if (ret) { | ||
1058 | ret = dell_smi_error(ret); | ||
1059 | goto out; | ||
1060 | } | ||
1061 | |||
1062 | info->modes = buffer->output[1] & 0xFFFF; | ||
1063 | info->type = (buffer->output[1] >> 24) & 0xFF; | ||
1064 | info->triggers = buffer->output[2] & 0xFF; | ||
1065 | units = (buffer->output[2] >> 8) & 0xFF; | ||
1066 | info->levels = (buffer->output[2] >> 16) & 0xFF; | ||
1067 | |||
1068 | if (units & BIT(0)) | ||
1069 | info->seconds = (buffer->output[3] >> 0) & 0xFF; | ||
1070 | if (units & BIT(1)) | ||
1071 | info->minutes = (buffer->output[3] >> 8) & 0xFF; | ||
1072 | if (units & BIT(2)) | ||
1073 | info->hours = (buffer->output[3] >> 16) & 0xFF; | ||
1074 | if (units & BIT(3)) | ||
1075 | info->days = (buffer->output[3] >> 24) & 0xFF; | ||
1076 | |||
1077 | out: | ||
1078 | release_buffer(); | ||
1079 | return ret; | ||
1080 | } | ||
1081 | |||
1082 | static unsigned int kbd_get_max_level(void) | ||
1083 | { | ||
1084 | if (kbd_info.levels != 0) | ||
1085 | return kbd_info.levels; | ||
1086 | if (kbd_mode_levels_count > 0) | ||
1087 | return kbd_mode_levels_count - 1; | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | static int kbd_get_level(struct kbd_state *state) | ||
1092 | { | ||
1093 | int i; | ||
1094 | |||
1095 | if (kbd_info.levels != 0) | ||
1096 | return state->level; | ||
1097 | |||
1098 | if (kbd_mode_levels_count > 0) { | ||
1099 | for (i = 0; i < kbd_mode_levels_count; ++i) | ||
1100 | if (kbd_mode_levels[i] == state->mode_bit) | ||
1101 | return i; | ||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | return -EINVAL; | ||
1106 | } | ||
1107 | |||
1108 | static int kbd_set_level(struct kbd_state *state, u8 level) | ||
1109 | { | ||
1110 | if (kbd_info.levels != 0) { | ||
1111 | if (level != 0) | ||
1112 | kbd_previous_level = level; | ||
1113 | if (state->level == level) | ||
1114 | return 0; | ||
1115 | state->level = level; | ||
1116 | if (level != 0 && state->mode_bit == KBD_MODE_BIT_OFF) | ||
1117 | state->mode_bit = kbd_previous_mode_bit; | ||
1118 | else if (level == 0 && state->mode_bit != KBD_MODE_BIT_OFF) { | ||
1119 | kbd_previous_mode_bit = state->mode_bit; | ||
1120 | state->mode_bit = KBD_MODE_BIT_OFF; | ||
1121 | } | ||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | if (kbd_mode_levels_count > 0 && level < kbd_mode_levels_count) { | ||
1126 | if (level != 0) | ||
1127 | kbd_previous_level = level; | ||
1128 | state->mode_bit = kbd_mode_levels[level]; | ||
1129 | return 0; | ||
1130 | } | ||
1131 | |||
1132 | return -EINVAL; | ||
1133 | } | ||
1134 | |||
1135 | static int kbd_get_state(struct kbd_state *state) | ||
1136 | { | ||
1137 | int ret; | ||
1138 | |||
1139 | get_buffer(); | ||
1140 | |||
1141 | buffer->input[0] = 0x1; | ||
1142 | dell_send_request(buffer, 4, 11); | ||
1143 | ret = buffer->output[0]; | ||
1144 | |||
1145 | if (ret) { | ||
1146 | ret = dell_smi_error(ret); | ||
1147 | goto out; | ||
1148 | } | ||
1149 | |||
1150 | state->mode_bit = ffs(buffer->output[1] & 0xFFFF); | ||
1151 | if (state->mode_bit != 0) | ||
1152 | state->mode_bit--; | ||
1153 | |||
1154 | state->triggers = (buffer->output[1] >> 16) & 0xFF; | ||
1155 | state->timeout_value = (buffer->output[1] >> 24) & 0x3F; | ||
1156 | state->timeout_unit = (buffer->output[1] >> 30) & 0x3; | ||
1157 | state->als_setting = buffer->output[2] & 0xFF; | ||
1158 | state->als_value = (buffer->output[2] >> 8) & 0xFF; | ||
1159 | state->level = (buffer->output[2] >> 16) & 0xFF; | ||
1160 | |||
1161 | out: | ||
1162 | release_buffer(); | ||
1163 | return ret; | ||
1164 | } | ||
1165 | |||
1166 | static int kbd_set_state(struct kbd_state *state) | ||
1167 | { | ||
1168 | int ret; | ||
1169 | |||
1170 | get_buffer(); | ||
1171 | buffer->input[0] = 0x2; | ||
1172 | buffer->input[1] = BIT(state->mode_bit) & 0xFFFF; | ||
1173 | buffer->input[1] |= (state->triggers & 0xFF) << 16; | ||
1174 | buffer->input[1] |= (state->timeout_value & 0x3F) << 24; | ||
1175 | buffer->input[1] |= (state->timeout_unit & 0x3) << 30; | ||
1176 | buffer->input[2] = state->als_setting & 0xFF; | ||
1177 | buffer->input[2] |= (state->level & 0xFF) << 16; | ||
1178 | dell_send_request(buffer, 4, 11); | ||
1179 | ret = buffer->output[0]; | ||
1180 | release_buffer(); | ||
1181 | |||
1182 | return dell_smi_error(ret); | ||
1183 | } | ||
1184 | |||
1185 | static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old) | ||
1186 | { | ||
1187 | int ret; | ||
1188 | |||
1189 | ret = kbd_set_state(state); | ||
1190 | if (ret == 0) | ||
1191 | return 0; | ||
1192 | |||
1193 | /* | ||
1194 | * When setting the new state fails,try to restore the previous one. | ||
1195 | * This is needed on some machines where BIOS sets a default state when | ||
1196 | * setting a new state fails. This default state could be all off. | ||
1197 | */ | ||
1198 | |||
1199 | if (kbd_set_state(old)) | ||
1200 | pr_err("Setting old previous keyboard state failed\n"); | ||
1201 | |||
1202 | return ret; | ||
1203 | } | ||
1204 | |||
1205 | static int kbd_set_token_bit(u8 bit) | ||
1206 | { | ||
1207 | int id; | ||
1208 | int ret; | ||
1209 | |||
1210 | if (bit >= ARRAY_SIZE(kbd_tokens)) | ||
1211 | return -EINVAL; | ||
1212 | |||
1213 | id = find_token_id(kbd_tokens[bit]); | ||
1214 | if (id == -1) | ||
1215 | return -EINVAL; | ||
1216 | |||
1217 | get_buffer(); | ||
1218 | buffer->input[0] = da_tokens[id].location; | ||
1219 | buffer->input[1] = da_tokens[id].value; | ||
1220 | dell_send_request(buffer, 1, 0); | ||
1221 | ret = buffer->output[0]; | ||
1222 | release_buffer(); | ||
1223 | |||
1224 | return dell_smi_error(ret); | ||
1225 | } | ||
1226 | |||
1227 | static int kbd_get_token_bit(u8 bit) | ||
1228 | { | ||
1229 | int id; | ||
1230 | int ret; | ||
1231 | int val; | ||
1232 | |||
1233 | if (bit >= ARRAY_SIZE(kbd_tokens)) | ||
1234 | return -EINVAL; | ||
1235 | |||
1236 | id = find_token_id(kbd_tokens[bit]); | ||
1237 | if (id == -1) | ||
1238 | return -EINVAL; | ||
1239 | |||
1240 | get_buffer(); | ||
1241 | buffer->input[0] = da_tokens[id].location; | ||
1242 | dell_send_request(buffer, 0, 0); | ||
1243 | ret = buffer->output[0]; | ||
1244 | val = buffer->output[1]; | ||
1245 | release_buffer(); | ||
1246 | |||
1247 | if (ret) | ||
1248 | return dell_smi_error(ret); | ||
1249 | |||
1250 | return (val == da_tokens[id].value); | ||
1251 | } | ||
1252 | |||
1253 | static int kbd_get_first_active_token_bit(void) | ||
1254 | { | ||
1255 | int i; | ||
1256 | int ret; | ||
1257 | |||
1258 | for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i) { | ||
1259 | ret = kbd_get_token_bit(i); | ||
1260 | if (ret == 1) | ||
1261 | return i; | ||
1262 | } | ||
1263 | |||
1264 | return ret; | ||
1265 | } | ||
1266 | |||
1267 | static int kbd_get_valid_token_counts(void) | ||
1268 | { | ||
1269 | return hweight16(kbd_token_bits); | ||
1270 | } | ||
1271 | |||
1272 | static inline int kbd_init_info(void) | ||
1273 | { | ||
1274 | struct kbd_state state; | ||
1275 | int ret; | ||
1276 | int i; | ||
1277 | |||
1278 | ret = kbd_get_info(&kbd_info); | ||
1279 | if (ret) | ||
1280 | return ret; | ||
1281 | |||
1282 | kbd_get_state(&state); | ||
1283 | |||
1284 | /* NOTE: timeout value is stored in 6 bits so max value is 63 */ | ||
1285 | if (kbd_info.seconds > 63) | ||
1286 | kbd_info.seconds = 63; | ||
1287 | if (kbd_info.minutes > 63) | ||
1288 | kbd_info.minutes = 63; | ||
1289 | if (kbd_info.hours > 63) | ||
1290 | kbd_info.hours = 63; | ||
1291 | if (kbd_info.days > 63) | ||
1292 | kbd_info.days = 63; | ||
1293 | |||
1294 | /* NOTE: On tested machines ON mode did not work and caused | ||
1295 | * problems (turned backlight off) so do not use it | ||
1296 | */ | ||
1297 | kbd_info.modes &= ~BIT(KBD_MODE_BIT_ON); | ||
1298 | |||
1299 | kbd_previous_level = kbd_get_level(&state); | ||
1300 | kbd_previous_mode_bit = state.mode_bit; | ||
1301 | |||
1302 | if (kbd_previous_level == 0 && kbd_get_max_level() != 0) | ||
1303 | kbd_previous_level = 1; | ||
1304 | |||
1305 | if (kbd_previous_mode_bit == KBD_MODE_BIT_OFF) { | ||
1306 | kbd_previous_mode_bit = | ||
1307 | ffs(kbd_info.modes & ~BIT(KBD_MODE_BIT_OFF)); | ||
1308 | if (kbd_previous_mode_bit != 0) | ||
1309 | kbd_previous_mode_bit--; | ||
1310 | } | ||
1311 | |||
1312 | if (kbd_info.modes & (BIT(KBD_MODE_BIT_ALS) | | ||
1313 | BIT(KBD_MODE_BIT_TRIGGER_ALS))) | ||
1314 | kbd_als_supported = true; | ||
1315 | |||
1316 | if (kbd_info.modes & ( | ||
1317 | BIT(KBD_MODE_BIT_TRIGGER_ALS) | BIT(KBD_MODE_BIT_TRIGGER) | | ||
1318 | BIT(KBD_MODE_BIT_TRIGGER_25) | BIT(KBD_MODE_BIT_TRIGGER_50) | | ||
1319 | BIT(KBD_MODE_BIT_TRIGGER_75) | BIT(KBD_MODE_BIT_TRIGGER_100) | ||
1320 | )) | ||
1321 | kbd_triggers_supported = true; | ||
1322 | |||
1323 | /* kbd_mode_levels[0] is reserved, see below */ | ||
1324 | for (i = 0; i < 16; ++i) | ||
1325 | if (kbd_is_level_mode_bit(i) && (BIT(i) & kbd_info.modes)) | ||
1326 | kbd_mode_levels[1 + kbd_mode_levels_count++] = i; | ||
1327 | |||
1328 | /* | ||
1329 | * Find the first supported mode and assign to kbd_mode_levels[0]. | ||
1330 | * This should be 0 (off), but we cannot depend on the BIOS to | ||
1331 | * support 0. | ||
1332 | */ | ||
1333 | if (kbd_mode_levels_count > 0) { | ||
1334 | for (i = 0; i < 16; ++i) { | ||
1335 | if (BIT(i) & kbd_info.modes) { | ||
1336 | kbd_mode_levels[0] = i; | ||
1337 | break; | ||
1338 | } | ||
1339 | } | ||
1340 | kbd_mode_levels_count++; | ||
1341 | } | ||
1342 | |||
1343 | return 0; | ||
1344 | |||
1345 | } | ||
1346 | |||
1347 | static inline void kbd_init_tokens(void) | ||
1348 | { | ||
1349 | int i; | ||
1350 | |||
1351 | for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i) | ||
1352 | if (find_token_id(kbd_tokens[i]) != -1) | ||
1353 | kbd_token_bits |= BIT(i); | ||
1354 | } | ||
1355 | |||
1356 | static void kbd_init(void) | ||
1357 | { | ||
1358 | int ret; | ||
1359 | |||
1360 | ret = kbd_init_info(); | ||
1361 | kbd_init_tokens(); | ||
1362 | |||
1363 | if (kbd_token_bits != 0 || ret == 0) | ||
1364 | kbd_led_present = true; | ||
1365 | } | ||
1366 | |||
1367 | static ssize_t kbd_led_timeout_store(struct device *dev, | ||
1368 | struct device_attribute *attr, | ||
1369 | const char *buf, size_t count) | ||
1370 | { | ||
1371 | struct kbd_state new_state; | ||
1372 | struct kbd_state state; | ||
1373 | bool convert; | ||
1374 | int value; | ||
1375 | int ret; | ||
1376 | char ch; | ||
1377 | u8 unit; | ||
1378 | int i; | ||
1379 | |||
1380 | ret = sscanf(buf, "%d %c", &value, &ch); | ||
1381 | if (ret < 1) | ||
1382 | return -EINVAL; | ||
1383 | else if (ret == 1) | ||
1384 | ch = 's'; | ||
1385 | |||
1386 | if (value < 0) | ||
1387 | return -EINVAL; | ||
1388 | |||
1389 | convert = false; | ||
1390 | |||
1391 | switch (ch) { | ||
1392 | case 's': | ||
1393 | if (value > kbd_info.seconds) | ||
1394 | convert = true; | ||
1395 | unit = KBD_TIMEOUT_SECONDS; | ||
1396 | break; | ||
1397 | case 'm': | ||
1398 | if (value > kbd_info.minutes) | ||
1399 | convert = true; | ||
1400 | unit = KBD_TIMEOUT_MINUTES; | ||
1401 | break; | ||
1402 | case 'h': | ||
1403 | if (value > kbd_info.hours) | ||
1404 | convert = true; | ||
1405 | unit = KBD_TIMEOUT_HOURS; | ||
1406 | break; | ||
1407 | case 'd': | ||
1408 | if (value > kbd_info.days) | ||
1409 | convert = true; | ||
1410 | unit = KBD_TIMEOUT_DAYS; | ||
1411 | break; | ||
1412 | default: | ||
1413 | return -EINVAL; | ||
1414 | } | ||
1415 | |||
1416 | if (quirks && quirks->needs_kbd_timeouts) | ||
1417 | convert = true; | ||
1418 | |||
1419 | if (convert) { | ||
1420 | /* Convert value from current units to seconds */ | ||
1421 | switch (unit) { | ||
1422 | case KBD_TIMEOUT_DAYS: | ||
1423 | value *= 24; | ||
1424 | case KBD_TIMEOUT_HOURS: | ||
1425 | value *= 60; | ||
1426 | case KBD_TIMEOUT_MINUTES: | ||
1427 | value *= 60; | ||
1428 | unit = KBD_TIMEOUT_SECONDS; | ||
1429 | } | ||
1430 | |||
1431 | if (quirks && quirks->needs_kbd_timeouts) { | ||
1432 | for (i = 0; quirks->kbd_timeouts[i] != -1; i++) { | ||
1433 | if (value <= quirks->kbd_timeouts[i]) { | ||
1434 | value = quirks->kbd_timeouts[i]; | ||
1435 | break; | ||
1436 | } | ||
1437 | } | ||
1438 | } | ||
1439 | |||
1440 | if (value <= kbd_info.seconds && kbd_info.seconds) { | ||
1441 | unit = KBD_TIMEOUT_SECONDS; | ||
1442 | } else if (value / 60 <= kbd_info.minutes && kbd_info.minutes) { | ||
1443 | value /= 60; | ||
1444 | unit = KBD_TIMEOUT_MINUTES; | ||
1445 | } else if (value / (60 * 60) <= kbd_info.hours && kbd_info.hours) { | ||
1446 | value /= (60 * 60); | ||
1447 | unit = KBD_TIMEOUT_HOURS; | ||
1448 | } else if (value / (60 * 60 * 24) <= kbd_info.days && kbd_info.days) { | ||
1449 | value /= (60 * 60 * 24); | ||
1450 | unit = KBD_TIMEOUT_DAYS; | ||
1451 | } else { | ||
1452 | return -EINVAL; | ||
1453 | } | ||
1454 | } | ||
1455 | |||
1456 | ret = kbd_get_state(&state); | ||
1457 | if (ret) | ||
1458 | return ret; | ||
1459 | |||
1460 | new_state = state; | ||
1461 | new_state.timeout_value = value; | ||
1462 | new_state.timeout_unit = unit; | ||
1463 | |||
1464 | ret = kbd_set_state_safe(&new_state, &state); | ||
1465 | if (ret) | ||
1466 | return ret; | ||
1467 | |||
1468 | return count; | ||
1469 | } | ||
1470 | |||
1471 | static ssize_t kbd_led_timeout_show(struct device *dev, | ||
1472 | struct device_attribute *attr, char *buf) | ||
1473 | { | ||
1474 | struct kbd_state state; | ||
1475 | int ret; | ||
1476 | int len; | ||
1477 | |||
1478 | ret = kbd_get_state(&state); | ||
1479 | if (ret) | ||
1480 | return ret; | ||
1481 | |||
1482 | len = sprintf(buf, "%d", state.timeout_value); | ||
1483 | |||
1484 | switch (state.timeout_unit) { | ||
1485 | case KBD_TIMEOUT_SECONDS: | ||
1486 | return len + sprintf(buf+len, "s\n"); | ||
1487 | case KBD_TIMEOUT_MINUTES: | ||
1488 | return len + sprintf(buf+len, "m\n"); | ||
1489 | case KBD_TIMEOUT_HOURS: | ||
1490 | return len + sprintf(buf+len, "h\n"); | ||
1491 | case KBD_TIMEOUT_DAYS: | ||
1492 | return len + sprintf(buf+len, "d\n"); | ||
1493 | default: | ||
1494 | return -EINVAL; | ||
1495 | } | ||
1496 | |||
1497 | return len; | ||
1498 | } | ||
1499 | |||
1500 | static DEVICE_ATTR(stop_timeout, S_IRUGO | S_IWUSR, | ||
1501 | kbd_led_timeout_show, kbd_led_timeout_store); | ||
1502 | |||
1503 | static const char * const kbd_led_triggers[] = { | ||
1504 | "keyboard", | ||
1505 | "touchpad", | ||
1506 | /*"trackstick"*/ NULL, /* NOTE: trackstick is just alias for touchpad */ | ||
1507 | "mouse", | ||
1508 | }; | ||
1509 | |||
1510 | static ssize_t kbd_led_triggers_store(struct device *dev, | ||
1511 | struct device_attribute *attr, | ||
1512 | const char *buf, size_t count) | ||
1513 | { | ||
1514 | struct kbd_state new_state; | ||
1515 | struct kbd_state state; | ||
1516 | bool triggers_enabled = false; | ||
1517 | int trigger_bit = -1; | ||
1518 | char trigger[21]; | ||
1519 | int i, ret; | ||
1520 | |||
1521 | ret = sscanf(buf, "%20s", trigger); | ||
1522 | if (ret != 1) | ||
1523 | return -EINVAL; | ||
1524 | |||
1525 | if (trigger[0] != '+' && trigger[0] != '-') | ||
1526 | return -EINVAL; | ||
1527 | |||
1528 | ret = kbd_get_state(&state); | ||
1529 | if (ret) | ||
1530 | return ret; | ||
1531 | |||
1532 | if (kbd_triggers_supported) | ||
1533 | triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit); | ||
1534 | |||
1535 | if (kbd_triggers_supported) { | ||
1536 | for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); ++i) { | ||
1537 | if (!(kbd_info.triggers & BIT(i))) | ||
1538 | continue; | ||
1539 | if (!kbd_led_triggers[i]) | ||
1540 | continue; | ||
1541 | if (strcmp(trigger+1, kbd_led_triggers[i]) != 0) | ||
1542 | continue; | ||
1543 | if (trigger[0] == '+' && | ||
1544 | triggers_enabled && (state.triggers & BIT(i))) | ||
1545 | return count; | ||
1546 | if (trigger[0] == '-' && | ||
1547 | (!triggers_enabled || !(state.triggers & BIT(i)))) | ||
1548 | return count; | ||
1549 | trigger_bit = i; | ||
1550 | break; | ||
1551 | } | ||
1552 | } | ||
1553 | |||
1554 | if (trigger_bit != -1) { | ||
1555 | new_state = state; | ||
1556 | if (trigger[0] == '+') | ||
1557 | new_state.triggers |= BIT(trigger_bit); | ||
1558 | else { | ||
1559 | new_state.triggers &= ~BIT(trigger_bit); | ||
1560 | /* NOTE: trackstick bit (2) must be disabled when | ||
1561 | * disabling touchpad bit (1), otherwise touchpad | ||
1562 | * bit (1) will not be disabled */ | ||
1563 | if (trigger_bit == 1) | ||
1564 | new_state.triggers &= ~BIT(2); | ||
1565 | } | ||
1566 | if ((kbd_info.triggers & new_state.triggers) != | ||
1567 | new_state.triggers) | ||
1568 | return -EINVAL; | ||
1569 | if (new_state.triggers && !triggers_enabled) { | ||
1570 | new_state.mode_bit = KBD_MODE_BIT_TRIGGER; | ||
1571 | kbd_set_level(&new_state, kbd_previous_level); | ||
1572 | } else if (new_state.triggers == 0) { | ||
1573 | kbd_set_level(&new_state, 0); | ||
1574 | } | ||
1575 | if (!(kbd_info.modes & BIT(new_state.mode_bit))) | ||
1576 | return -EINVAL; | ||
1577 | ret = kbd_set_state_safe(&new_state, &state); | ||
1578 | if (ret) | ||
1579 | return ret; | ||
1580 | if (new_state.mode_bit != KBD_MODE_BIT_OFF) | ||
1581 | kbd_previous_mode_bit = new_state.mode_bit; | ||
1582 | return count; | ||
1583 | } | ||
1584 | |||
1585 | return -EINVAL; | ||
1586 | } | ||
1587 | |||
1588 | static ssize_t kbd_led_triggers_show(struct device *dev, | ||
1589 | struct device_attribute *attr, char *buf) | ||
1590 | { | ||
1591 | struct kbd_state state; | ||
1592 | bool triggers_enabled; | ||
1593 | int level, i, ret; | ||
1594 | int len = 0; | ||
1595 | |||
1596 | ret = kbd_get_state(&state); | ||
1597 | if (ret) | ||
1598 | return ret; | ||
1599 | |||
1600 | len = 0; | ||
1601 | |||
1602 | if (kbd_triggers_supported) { | ||
1603 | triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit); | ||
1604 | level = kbd_get_level(&state); | ||
1605 | for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); ++i) { | ||
1606 | if (!(kbd_info.triggers & BIT(i))) | ||
1607 | continue; | ||
1608 | if (!kbd_led_triggers[i]) | ||
1609 | continue; | ||
1610 | if ((triggers_enabled || level <= 0) && | ||
1611 | (state.triggers & BIT(i))) | ||
1612 | buf[len++] = '+'; | ||
1613 | else | ||
1614 | buf[len++] = '-'; | ||
1615 | len += sprintf(buf+len, "%s ", kbd_led_triggers[i]); | ||
1616 | } | ||
1617 | } | ||
1618 | |||
1619 | if (len) | ||
1620 | buf[len - 1] = '\n'; | ||
1621 | |||
1622 | return len; | ||
1623 | } | ||
1624 | |||
1625 | static DEVICE_ATTR(start_triggers, S_IRUGO | S_IWUSR, | ||
1626 | kbd_led_triggers_show, kbd_led_triggers_store); | ||
1627 | |||
1628 | static ssize_t kbd_led_als_enabled_store(struct device *dev, | ||
1629 | struct device_attribute *attr, | ||
1630 | const char *buf, size_t count) | ||
1631 | { | ||
1632 | struct kbd_state new_state; | ||
1633 | struct kbd_state state; | ||
1634 | bool triggers_enabled = false; | ||
1635 | int enable; | ||
1636 | int ret; | ||
1637 | |||
1638 | ret = kstrtoint(buf, 0, &enable); | ||
1639 | if (ret) | ||
1640 | return ret; | ||
1641 | |||
1642 | ret = kbd_get_state(&state); | ||
1643 | if (ret) | ||
1644 | return ret; | ||
1645 | |||
1646 | if (enable == kbd_is_als_mode_bit(state.mode_bit)) | ||
1647 | return count; | ||
1648 | |||
1649 | new_state = state; | ||
1650 | |||
1651 | if (kbd_triggers_supported) | ||
1652 | triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit); | ||
1653 | |||
1654 | if (enable) { | ||
1655 | if (triggers_enabled) | ||
1656 | new_state.mode_bit = KBD_MODE_BIT_TRIGGER_ALS; | ||
1657 | else | ||
1658 | new_state.mode_bit = KBD_MODE_BIT_ALS; | ||
1659 | } else { | ||
1660 | if (triggers_enabled) { | ||
1661 | new_state.mode_bit = KBD_MODE_BIT_TRIGGER; | ||
1662 | kbd_set_level(&new_state, kbd_previous_level); | ||
1663 | } else { | ||
1664 | new_state.mode_bit = KBD_MODE_BIT_ON; | ||
1665 | } | ||
1666 | } | ||
1667 | if (!(kbd_info.modes & BIT(new_state.mode_bit))) | ||
1668 | return -EINVAL; | ||
1669 | |||
1670 | ret = kbd_set_state_safe(&new_state, &state); | ||
1671 | if (ret) | ||
1672 | return ret; | ||
1673 | kbd_previous_mode_bit = new_state.mode_bit; | ||
1674 | |||
1675 | return count; | ||
1676 | } | ||
1677 | |||
1678 | static ssize_t kbd_led_als_enabled_show(struct device *dev, | ||
1679 | struct device_attribute *attr, | ||
1680 | char *buf) | ||
1681 | { | ||
1682 | struct kbd_state state; | ||
1683 | bool enabled = false; | ||
1684 | int ret; | ||
1685 | |||
1686 | ret = kbd_get_state(&state); | ||
1687 | if (ret) | ||
1688 | return ret; | ||
1689 | enabled = kbd_is_als_mode_bit(state.mode_bit); | ||
1690 | |||
1691 | return sprintf(buf, "%d\n", enabled ? 1 : 0); | ||
1692 | } | ||
1693 | |||
1694 | static DEVICE_ATTR(als_enabled, S_IRUGO | S_IWUSR, | ||
1695 | kbd_led_als_enabled_show, kbd_led_als_enabled_store); | ||
1696 | |||
1697 | static ssize_t kbd_led_als_setting_store(struct device *dev, | ||
1698 | struct device_attribute *attr, | ||
1699 | const char *buf, size_t count) | ||
1700 | { | ||
1701 | struct kbd_state state; | ||
1702 | struct kbd_state new_state; | ||
1703 | u8 setting; | ||
1704 | int ret; | ||
1705 | |||
1706 | ret = kstrtou8(buf, 10, &setting); | ||
1707 | if (ret) | ||
1708 | return ret; | ||
1709 | |||
1710 | ret = kbd_get_state(&state); | ||
1711 | if (ret) | ||
1712 | return ret; | ||
1713 | |||
1714 | new_state = state; | ||
1715 | new_state.als_setting = setting; | ||
1716 | |||
1717 | ret = kbd_set_state_safe(&new_state, &state); | ||
1718 | if (ret) | ||
1719 | return ret; | ||
1720 | |||
1721 | return count; | ||
1722 | } | ||
1723 | |||
1724 | static ssize_t kbd_led_als_setting_show(struct device *dev, | ||
1725 | struct device_attribute *attr, | ||
1726 | char *buf) | ||
1727 | { | ||
1728 | struct kbd_state state; | ||
1729 | int ret; | ||
1730 | |||
1731 | ret = kbd_get_state(&state); | ||
1732 | if (ret) | ||
1733 | return ret; | ||
1734 | |||
1735 | return sprintf(buf, "%d\n", state.als_setting); | ||
1736 | } | ||
1737 | |||
1738 | static DEVICE_ATTR(als_setting, S_IRUGO | S_IWUSR, | ||
1739 | kbd_led_als_setting_show, kbd_led_als_setting_store); | ||
1740 | |||
1741 | static struct attribute *kbd_led_attrs[] = { | ||
1742 | &dev_attr_stop_timeout.attr, | ||
1743 | &dev_attr_start_triggers.attr, | ||
1744 | NULL, | ||
1745 | }; | ||
1746 | |||
1747 | static const struct attribute_group kbd_led_group = { | ||
1748 | .attrs = kbd_led_attrs, | ||
1749 | }; | ||
1750 | |||
1751 | static struct attribute *kbd_led_als_attrs[] = { | ||
1752 | &dev_attr_als_enabled.attr, | ||
1753 | &dev_attr_als_setting.attr, | ||
1754 | NULL, | ||
1755 | }; | ||
1756 | |||
1757 | static const struct attribute_group kbd_led_als_group = { | ||
1758 | .attrs = kbd_led_als_attrs, | ||
1759 | }; | ||
1760 | |||
1761 | static const struct attribute_group *kbd_led_groups[] = { | ||
1762 | &kbd_led_group, | ||
1763 | &kbd_led_als_group, | ||
1764 | NULL, | ||
1765 | }; | ||
1766 | |||
1767 | static enum led_brightness kbd_led_level_get(struct led_classdev *led_cdev) | ||
1768 | { | ||
1769 | int ret; | ||
1770 | u16 num; | ||
1771 | struct kbd_state state; | ||
1772 | |||
1773 | if (kbd_get_max_level()) { | ||
1774 | ret = kbd_get_state(&state); | ||
1775 | if (ret) | ||
1776 | return 0; | ||
1777 | ret = kbd_get_level(&state); | ||
1778 | if (ret < 0) | ||
1779 | return 0; | ||
1780 | return ret; | ||
1781 | } | ||
1782 | |||
1783 | if (kbd_get_valid_token_counts()) { | ||
1784 | ret = kbd_get_first_active_token_bit(); | ||
1785 | if (ret < 0) | ||
1786 | return 0; | ||
1787 | for (num = kbd_token_bits; num != 0 && ret > 0; --ret) | ||
1788 | num &= num - 1; /* clear the first bit set */ | ||
1789 | if (num == 0) | ||
1790 | return 0; | ||
1791 | return ffs(num) - 1; | ||
1792 | } | ||
1793 | |||
1794 | pr_warn("Keyboard brightness level control not supported\n"); | ||
1795 | return 0; | ||
1796 | } | ||
1797 | |||
1798 | static void kbd_led_level_set(struct led_classdev *led_cdev, | ||
1799 | enum led_brightness value) | ||
1800 | { | ||
1801 | struct kbd_state state; | ||
1802 | struct kbd_state new_state; | ||
1803 | u16 num; | ||
1804 | |||
1805 | if (kbd_get_max_level()) { | ||
1806 | if (kbd_get_state(&state)) | ||
1807 | return; | ||
1808 | new_state = state; | ||
1809 | if (kbd_set_level(&new_state, value)) | ||
1810 | return; | ||
1811 | kbd_set_state_safe(&new_state, &state); | ||
1812 | return; | ||
1813 | } | ||
1814 | |||
1815 | if (kbd_get_valid_token_counts()) { | ||
1816 | for (num = kbd_token_bits; num != 0 && value > 0; --value) | ||
1817 | num &= num - 1; /* clear the first bit set */ | ||
1818 | if (num == 0) | ||
1819 | return; | ||
1820 | kbd_set_token_bit(ffs(num) - 1); | ||
1821 | return; | ||
1822 | } | ||
1823 | |||
1824 | pr_warn("Keyboard brightness level control not supported\n"); | ||
1825 | } | ||
1826 | |||
1827 | static struct led_classdev kbd_led = { | ||
1828 | .name = "dell::kbd_backlight", | ||
1829 | .brightness_set = kbd_led_level_set, | ||
1830 | .brightness_get = kbd_led_level_get, | ||
1831 | .groups = kbd_led_groups, | ||
1832 | }; | ||
1833 | |||
1834 | static int __init kbd_led_init(struct device *dev) | ||
1835 | { | ||
1836 | kbd_init(); | ||
1837 | if (!kbd_led_present) | ||
1838 | return -ENODEV; | ||
1839 | if (!kbd_als_supported) | ||
1840 | kbd_led_groups[1] = NULL; | ||
1841 | kbd_led.max_brightness = kbd_get_max_level(); | ||
1842 | if (!kbd_led.max_brightness) { | ||
1843 | kbd_led.max_brightness = kbd_get_valid_token_counts(); | ||
1844 | if (kbd_led.max_brightness) | ||
1845 | kbd_led.max_brightness--; | ||
1846 | } | ||
1847 | return led_classdev_register(dev, &kbd_led); | ||
1848 | } | ||
1849 | |||
1850 | static void brightness_set_exit(struct led_classdev *led_cdev, | ||
1851 | enum led_brightness value) | ||
1852 | { | ||
1853 | /* Don't change backlight level on exit */ | ||
1854 | }; | ||
1855 | |||
1856 | static void kbd_led_exit(void) | ||
1857 | { | ||
1858 | if (!kbd_led_present) | ||
1859 | return; | ||
1860 | kbd_led.brightness_set = brightness_set_exit; | ||
1861 | led_classdev_unregister(&kbd_led); | ||
1862 | } | ||
1863 | |||
792 | static int __init dell_init(void) | 1864 | static int __init dell_init(void) |
793 | { | 1865 | { |
794 | int max_intensity = 0; | 1866 | int max_intensity = 0; |
@@ -841,6 +1913,8 @@ static int __init dell_init(void) | |||
841 | if (quirks && quirks->touchpad_led) | 1913 | if (quirks && quirks->touchpad_led) |
842 | touchpad_led_init(&platform_device->dev); | 1914 | touchpad_led_init(&platform_device->dev); |
843 | 1915 | ||
1916 | kbd_led_init(&platform_device->dev); | ||
1917 | |||
844 | dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); | 1918 | dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); |
845 | if (dell_laptop_dir != NULL) | 1919 | if (dell_laptop_dir != NULL) |
846 | debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, | 1920 | debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, |
@@ -908,6 +1982,7 @@ static void __exit dell_exit(void) | |||
908 | debugfs_remove_recursive(dell_laptop_dir); | 1982 | debugfs_remove_recursive(dell_laptop_dir); |
909 | if (quirks && quirks->touchpad_led) | 1983 | if (quirks && quirks->touchpad_led) |
910 | touchpad_led_exit(); | 1984 | touchpad_led_exit(); |
1985 | kbd_led_exit(); | ||
911 | i8042_remove_filter(dell_laptop_i8042_filter); | 1986 | i8042_remove_filter(dell_laptop_i8042_filter); |
912 | cancel_delayed_work_sync(&dell_rfkill_work); | 1987 | cancel_delayed_work_sync(&dell_rfkill_work); |
913 | backlight_device_unregister(dell_backlight_device); | 1988 | backlight_device_unregister(dell_backlight_device); |
@@ -924,5 +1999,7 @@ module_init(dell_init); | |||
924 | module_exit(dell_exit); | 1999 | module_exit(dell_exit); |
925 | 2000 | ||
926 | MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); | 2001 | MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); |
2002 | MODULE_AUTHOR("Gabriele Mazzotta <gabriele.mzt@gmail.com>"); | ||
2003 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); | ||
927 | MODULE_DESCRIPTION("Dell laptop driver"); | 2004 | MODULE_DESCRIPTION("Dell laptop driver"); |
928 | MODULE_LICENSE("GPL"); | 2005 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/platform/x86/intel_oaktrail.c b/drivers/platform/x86/intel_oaktrail.c index a4a4258f6134..8037c8b46241 100644 --- a/drivers/platform/x86/intel_oaktrail.c +++ b/drivers/platform/x86/intel_oaktrail.c | |||
@@ -62,7 +62,7 @@ | |||
62 | * (1 << 1): Bluetooth enable/disable, RW. | 62 | * (1 << 1): Bluetooth enable/disable, RW. |
63 | * (1 << 2): GPS enable/disable, RW. | 63 | * (1 << 2): GPS enable/disable, RW. |
64 | * (1 << 3): WiFi enable/disable, RW. | 64 | * (1 << 3): WiFi enable/disable, RW. |
65 | * (1 << 4): WWAN (3G) enable/disalbe, RW. | 65 | * (1 << 4): WWAN (3G) enable/disable, RW. |
66 | * (1 << 5): Touchscreen enable/disable, Read Only. | 66 | * (1 << 5): Touchscreen enable/disable, Read Only. |
67 | */ | 67 | */ |
68 | #define OT_EC_DEVICE_STATE_ADDRESS 0xD6 | 68 | #define OT_EC_DEVICE_STATE_ADDRESS 0xD6 |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 3b8ceee7c5cb..7769575345d8 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -319,6 +319,7 @@ static struct { | |||
319 | u32 sensors_pdrv_attrs_registered:1; | 319 | u32 sensors_pdrv_attrs_registered:1; |
320 | u32 sensors_pdev_attrs_registered:1; | 320 | u32 sensors_pdev_attrs_registered:1; |
321 | u32 hotkey_poll_active:1; | 321 | u32 hotkey_poll_active:1; |
322 | u32 has_adaptive_kbd:1; | ||
322 | } tp_features; | 323 | } tp_features; |
323 | 324 | ||
324 | static struct { | 325 | static struct { |
@@ -1911,6 +1912,27 @@ enum { /* hot key scan codes (derived from ACPI DSDT) */ | |||
1911 | TP_ACPI_HOTKEYSCAN_UNK7, | 1912 | TP_ACPI_HOTKEYSCAN_UNK7, |
1912 | TP_ACPI_HOTKEYSCAN_UNK8, | 1913 | TP_ACPI_HOTKEYSCAN_UNK8, |
1913 | 1914 | ||
1915 | TP_ACPI_HOTKEYSCAN_MUTE2, | ||
1916 | TP_ACPI_HOTKEYSCAN_BRIGHTNESS_ZERO, | ||
1917 | TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL, | ||
1918 | TP_ACPI_HOTKEYSCAN_CLOUD, | ||
1919 | TP_ACPI_HOTKEYSCAN_UNK9, | ||
1920 | TP_ACPI_HOTKEYSCAN_VOICE, | ||
1921 | TP_ACPI_HOTKEYSCAN_UNK10, | ||
1922 | TP_ACPI_HOTKEYSCAN_GESTURES, | ||
1923 | TP_ACPI_HOTKEYSCAN_UNK11, | ||
1924 | TP_ACPI_HOTKEYSCAN_UNK12, | ||
1925 | TP_ACPI_HOTKEYSCAN_UNK13, | ||
1926 | TP_ACPI_HOTKEYSCAN_CONFIG, | ||
1927 | TP_ACPI_HOTKEYSCAN_NEW_TAB, | ||
1928 | TP_ACPI_HOTKEYSCAN_RELOAD, | ||
1929 | TP_ACPI_HOTKEYSCAN_BACK, | ||
1930 | TP_ACPI_HOTKEYSCAN_MIC_DOWN, | ||
1931 | TP_ACPI_HOTKEYSCAN_MIC_UP, | ||
1932 | TP_ACPI_HOTKEYSCAN_MIC_CANCELLATION, | ||
1933 | TP_ACPI_HOTKEYSCAN_CAMERA_MODE, | ||
1934 | TP_ACPI_HOTKEYSCAN_ROTATE_DISPLAY, | ||
1935 | |||
1914 | /* Hotkey keymap size */ | 1936 | /* Hotkey keymap size */ |
1915 | TPACPI_HOTKEY_MAP_LEN | 1937 | TPACPI_HOTKEY_MAP_LEN |
1916 | }; | 1938 | }; |
@@ -2647,9 +2669,7 @@ static ssize_t hotkey_enable_store(struct device *dev, | |||
2647 | return count; | 2669 | return count; |
2648 | } | 2670 | } |
2649 | 2671 | ||
2650 | static struct device_attribute dev_attr_hotkey_enable = | 2672 | static DEVICE_ATTR_RW(hotkey_enable); |
2651 | __ATTR(hotkey_enable, S_IWUSR | S_IRUGO, | ||
2652 | hotkey_enable_show, hotkey_enable_store); | ||
2653 | 2673 | ||
2654 | /* sysfs hotkey mask --------------------------------------------------- */ | 2674 | /* sysfs hotkey mask --------------------------------------------------- */ |
2655 | static ssize_t hotkey_mask_show(struct device *dev, | 2675 | static ssize_t hotkey_mask_show(struct device *dev, |
@@ -2685,9 +2705,7 @@ static ssize_t hotkey_mask_store(struct device *dev, | |||
2685 | return (res) ? res : count; | 2705 | return (res) ? res : count; |
2686 | } | 2706 | } |
2687 | 2707 | ||
2688 | static struct device_attribute dev_attr_hotkey_mask = | 2708 | static DEVICE_ATTR_RW(hotkey_mask); |
2689 | __ATTR(hotkey_mask, S_IWUSR | S_IRUGO, | ||
2690 | hotkey_mask_show, hotkey_mask_store); | ||
2691 | 2709 | ||
2692 | /* sysfs hotkey bios_enabled ------------------------------------------- */ | 2710 | /* sysfs hotkey bios_enabled ------------------------------------------- */ |
2693 | static ssize_t hotkey_bios_enabled_show(struct device *dev, | 2711 | static ssize_t hotkey_bios_enabled_show(struct device *dev, |
@@ -2697,8 +2715,7 @@ static ssize_t hotkey_bios_enabled_show(struct device *dev, | |||
2697 | return sprintf(buf, "0\n"); | 2715 | return sprintf(buf, "0\n"); |
2698 | } | 2716 | } |
2699 | 2717 | ||
2700 | static struct device_attribute dev_attr_hotkey_bios_enabled = | 2718 | static DEVICE_ATTR_RO(hotkey_bios_enabled); |
2701 | __ATTR(hotkey_bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL); | ||
2702 | 2719 | ||
2703 | /* sysfs hotkey bios_mask ---------------------------------------------- */ | 2720 | /* sysfs hotkey bios_mask ---------------------------------------------- */ |
2704 | static ssize_t hotkey_bios_mask_show(struct device *dev, | 2721 | static ssize_t hotkey_bios_mask_show(struct device *dev, |
@@ -2710,8 +2727,7 @@ static ssize_t hotkey_bios_mask_show(struct device *dev, | |||
2710 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); | 2727 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); |
2711 | } | 2728 | } |
2712 | 2729 | ||
2713 | static struct device_attribute dev_attr_hotkey_bios_mask = | 2730 | static DEVICE_ATTR_RO(hotkey_bios_mask); |
2714 | __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); | ||
2715 | 2731 | ||
2716 | /* sysfs hotkey all_mask ----------------------------------------------- */ | 2732 | /* sysfs hotkey all_mask ----------------------------------------------- */ |
2717 | static ssize_t hotkey_all_mask_show(struct device *dev, | 2733 | static ssize_t hotkey_all_mask_show(struct device *dev, |
@@ -2722,8 +2738,7 @@ static ssize_t hotkey_all_mask_show(struct device *dev, | |||
2722 | hotkey_all_mask | hotkey_source_mask); | 2738 | hotkey_all_mask | hotkey_source_mask); |
2723 | } | 2739 | } |
2724 | 2740 | ||
2725 | static struct device_attribute dev_attr_hotkey_all_mask = | 2741 | static DEVICE_ATTR_RO(hotkey_all_mask); |
2726 | __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL); | ||
2727 | 2742 | ||
2728 | /* sysfs hotkey recommended_mask --------------------------------------- */ | 2743 | /* sysfs hotkey recommended_mask --------------------------------------- */ |
2729 | static ssize_t hotkey_recommended_mask_show(struct device *dev, | 2744 | static ssize_t hotkey_recommended_mask_show(struct device *dev, |
@@ -2735,9 +2750,7 @@ static ssize_t hotkey_recommended_mask_show(struct device *dev, | |||
2735 | & ~hotkey_reserved_mask); | 2750 | & ~hotkey_reserved_mask); |
2736 | } | 2751 | } |
2737 | 2752 | ||
2738 | static struct device_attribute dev_attr_hotkey_recommended_mask = | 2753 | static DEVICE_ATTR_RO(hotkey_recommended_mask); |
2739 | __ATTR(hotkey_recommended_mask, S_IRUGO, | ||
2740 | hotkey_recommended_mask_show, NULL); | ||
2741 | 2754 | ||
2742 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | 2755 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL |
2743 | 2756 | ||
@@ -2792,9 +2805,7 @@ static ssize_t hotkey_source_mask_store(struct device *dev, | |||
2792 | return (rc < 0) ? rc : count; | 2805 | return (rc < 0) ? rc : count; |
2793 | } | 2806 | } |
2794 | 2807 | ||
2795 | static struct device_attribute dev_attr_hotkey_source_mask = | 2808 | static DEVICE_ATTR_RW(hotkey_source_mask); |
2796 | __ATTR(hotkey_source_mask, S_IWUSR | S_IRUGO, | ||
2797 | hotkey_source_mask_show, hotkey_source_mask_store); | ||
2798 | 2809 | ||
2799 | /* sysfs hotkey hotkey_poll_freq --------------------------------------- */ | 2810 | /* sysfs hotkey hotkey_poll_freq --------------------------------------- */ |
2800 | static ssize_t hotkey_poll_freq_show(struct device *dev, | 2811 | static ssize_t hotkey_poll_freq_show(struct device *dev, |
@@ -2826,9 +2837,7 @@ static ssize_t hotkey_poll_freq_store(struct device *dev, | |||
2826 | return count; | 2837 | return count; |
2827 | } | 2838 | } |
2828 | 2839 | ||
2829 | static struct device_attribute dev_attr_hotkey_poll_freq = | 2840 | static DEVICE_ATTR_RW(hotkey_poll_freq); |
2830 | __ATTR(hotkey_poll_freq, S_IWUSR | S_IRUGO, | ||
2831 | hotkey_poll_freq_show, hotkey_poll_freq_store); | ||
2832 | 2841 | ||
2833 | #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ | 2842 | #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ |
2834 | 2843 | ||
@@ -2849,8 +2858,7 @@ static ssize_t hotkey_radio_sw_show(struct device *dev, | |||
2849 | (res == TPACPI_RFK_RADIO_OFF) ? 0 : 1); | 2858 | (res == TPACPI_RFK_RADIO_OFF) ? 0 : 1); |
2850 | } | 2859 | } |
2851 | 2860 | ||
2852 | static struct device_attribute dev_attr_hotkey_radio_sw = | 2861 | static DEVICE_ATTR_RO(hotkey_radio_sw); |
2853 | __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL); | ||
2854 | 2862 | ||
2855 | static void hotkey_radio_sw_notify_change(void) | 2863 | static void hotkey_radio_sw_notify_change(void) |
2856 | { | 2864 | { |
@@ -2872,8 +2880,7 @@ static ssize_t hotkey_tablet_mode_show(struct device *dev, | |||
2872 | return snprintf(buf, PAGE_SIZE, "%d\n", !!s); | 2880 | return snprintf(buf, PAGE_SIZE, "%d\n", !!s); |
2873 | } | 2881 | } |
2874 | 2882 | ||
2875 | static struct device_attribute dev_attr_hotkey_tablet_mode = | 2883 | static DEVICE_ATTR_RO(hotkey_tablet_mode); |
2876 | __ATTR(hotkey_tablet_mode, S_IRUGO, hotkey_tablet_mode_show, NULL); | ||
2877 | 2884 | ||
2878 | static void hotkey_tablet_mode_notify_change(void) | 2885 | static void hotkey_tablet_mode_notify_change(void) |
2879 | { | 2886 | { |
@@ -2890,8 +2897,7 @@ static ssize_t hotkey_wakeup_reason_show(struct device *dev, | |||
2890 | return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_wakeup_reason); | 2897 | return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_wakeup_reason); |
2891 | } | 2898 | } |
2892 | 2899 | ||
2893 | static struct device_attribute dev_attr_hotkey_wakeup_reason = | 2900 | static DEVICE_ATTR_RO(hotkey_wakeup_reason); |
2894 | __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL); | ||
2895 | 2901 | ||
2896 | static void hotkey_wakeup_reason_notify_change(void) | 2902 | static void hotkey_wakeup_reason_notify_change(void) |
2897 | { | 2903 | { |
@@ -2907,9 +2913,7 @@ static ssize_t hotkey_wakeup_hotunplug_complete_show(struct device *dev, | |||
2907 | return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_autosleep_ack); | 2913 | return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_autosleep_ack); |
2908 | } | 2914 | } |
2909 | 2915 | ||
2910 | static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete = | 2916 | static DEVICE_ATTR_RO(hotkey_wakeup_hotunplug_complete); |
2911 | __ATTR(wakeup_hotunplug_complete, S_IRUGO, | ||
2912 | hotkey_wakeup_hotunplug_complete_show, NULL); | ||
2913 | 2917 | ||
2914 | static void hotkey_wakeup_hotunplug_complete_notify_change(void) | 2918 | static void hotkey_wakeup_hotunplug_complete_notify_change(void) |
2915 | { | 2919 | { |
@@ -2917,6 +2921,57 @@ static void hotkey_wakeup_hotunplug_complete_notify_change(void) | |||
2917 | "wakeup_hotunplug_complete"); | 2921 | "wakeup_hotunplug_complete"); |
2918 | } | 2922 | } |
2919 | 2923 | ||
2924 | /* sysfs adaptive kbd mode --------------------------------------------- */ | ||
2925 | |||
2926 | static int adaptive_keyboard_get_mode(void); | ||
2927 | static int adaptive_keyboard_set_mode(int new_mode); | ||
2928 | |||
2929 | enum ADAPTIVE_KEY_MODE { | ||
2930 | HOME_MODE, | ||
2931 | WEB_BROWSER_MODE, | ||
2932 | WEB_CONFERENCE_MODE, | ||
2933 | FUNCTION_MODE, | ||
2934 | LAYFLAT_MODE | ||
2935 | }; | ||
2936 | |||
2937 | static ssize_t adaptive_kbd_mode_show(struct device *dev, | ||
2938 | struct device_attribute *attr, | ||
2939 | char *buf) | ||
2940 | { | ||
2941 | int current_mode; | ||
2942 | |||
2943 | current_mode = adaptive_keyboard_get_mode(); | ||
2944 | if (current_mode < 0) | ||
2945 | return current_mode; | ||
2946 | |||
2947 | return snprintf(buf, PAGE_SIZE, "%d\n", current_mode); | ||
2948 | } | ||
2949 | |||
2950 | static ssize_t adaptive_kbd_mode_store(struct device *dev, | ||
2951 | struct device_attribute *attr, | ||
2952 | const char *buf, size_t count) | ||
2953 | { | ||
2954 | unsigned long t; | ||
2955 | int res; | ||
2956 | |||
2957 | if (parse_strtoul(buf, LAYFLAT_MODE, &t)) | ||
2958 | return -EINVAL; | ||
2959 | |||
2960 | res = adaptive_keyboard_set_mode(t); | ||
2961 | return (res < 0) ? res : count; | ||
2962 | } | ||
2963 | |||
2964 | static DEVICE_ATTR_RW(adaptive_kbd_mode); | ||
2965 | |||
2966 | static struct attribute *adaptive_kbd_attributes[] = { | ||
2967 | &dev_attr_adaptive_kbd_mode.attr, | ||
2968 | NULL | ||
2969 | }; | ||
2970 | |||
2971 | static const struct attribute_group adaptive_kbd_attr_group = { | ||
2972 | .attrs = adaptive_kbd_attributes, | ||
2973 | }; | ||
2974 | |||
2920 | /* --------------------------------------------------------------------- */ | 2975 | /* --------------------------------------------------------------------- */ |
2921 | 2976 | ||
2922 | static struct attribute *hotkey_attributes[] __initdata = { | 2977 | static struct attribute *hotkey_attributes[] __initdata = { |
@@ -3118,6 +3173,13 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
3118 | /* (assignments unknown, please report if found) */ | 3173 | /* (assignments unknown, please report if found) */ |
3119 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | 3174 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
3120 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | 3175 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
3176 | |||
3177 | /* No assignments, only used for Adaptive keyboards. */ | ||
3178 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
3179 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
3180 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
3181 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
3182 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
3121 | }, | 3183 | }, |
3122 | 3184 | ||
3123 | /* Generic keymap for Lenovo ThinkPads */ | 3185 | /* Generic keymap for Lenovo ThinkPads */ |
@@ -3174,6 +3236,35 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
3174 | 3236 | ||
3175 | /* Extra keys in use since the X240 / T440 / T540 */ | 3237 | /* Extra keys in use since the X240 / T440 / T540 */ |
3176 | KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE, | 3238 | KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE, |
3239 | |||
3240 | /* | ||
3241 | * These are the adaptive keyboard keycodes for Carbon X1 2014. | ||
3242 | * The first item in this list is the Mute button which is | ||
3243 | * emitted with 0x103 through | ||
3244 | * adaptive_keyboard_hotkey_notify_hotkey() when the sound | ||
3245 | * symbol is held. | ||
3246 | * We'll need to offset those by 0x20. | ||
3247 | */ | ||
3248 | KEY_RESERVED, /* Mute held, 0x103 */ | ||
3249 | KEY_BRIGHTNESS_MIN, /* Backlight off */ | ||
3250 | KEY_RESERVED, /* Clipping tool */ | ||
3251 | KEY_RESERVED, /* Cloud */ | ||
3252 | KEY_RESERVED, | ||
3253 | KEY_VOICECOMMAND, /* Voice */ | ||
3254 | KEY_RESERVED, | ||
3255 | KEY_RESERVED, /* Gestures */ | ||
3256 | KEY_RESERVED, | ||
3257 | KEY_RESERVED, | ||
3258 | KEY_RESERVED, | ||
3259 | KEY_CONFIG, /* Settings */ | ||
3260 | KEY_RESERVED, /* New tab */ | ||
3261 | KEY_REFRESH, /* Reload */ | ||
3262 | KEY_BACK, /* Back */ | ||
3263 | KEY_RESERVED, /* Microphone down */ | ||
3264 | KEY_RESERVED, /* Microphone up */ | ||
3265 | KEY_RESERVED, /* Microphone cancellation */ | ||
3266 | KEY_RESERVED, /* Camera mode */ | ||
3267 | KEY_RESERVED, /* Rotate display, 0x116 */ | ||
3177 | }, | 3268 | }, |
3178 | }; | 3269 | }; |
3179 | 3270 | ||
@@ -3227,6 +3318,20 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
3227 | if (!tp_features.hotkey) | 3318 | if (!tp_features.hotkey) |
3228 | return 1; | 3319 | return 1; |
3229 | 3320 | ||
3321 | /* | ||
3322 | * Check if we have an adaptive keyboard, like on the | ||
3323 | * Lenovo Carbon X1 2014 (2nd Gen). | ||
3324 | */ | ||
3325 | if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { | ||
3326 | if ((hkeyv >> 8) == 2) { | ||
3327 | tp_features.has_adaptive_kbd = true; | ||
3328 | res = sysfs_create_group(&tpacpi_pdev->dev.kobj, | ||
3329 | &adaptive_kbd_attr_group); | ||
3330 | if (res) | ||
3331 | goto err_exit; | ||
3332 | } | ||
3333 | } | ||
3334 | |||
3230 | quirks = tpacpi_check_quirks(tpacpi_hotkey_qtable, | 3335 | quirks = tpacpi_check_quirks(tpacpi_hotkey_qtable, |
3231 | ARRAY_SIZE(tpacpi_hotkey_qtable)); | 3336 | ARRAY_SIZE(tpacpi_hotkey_qtable)); |
3232 | 3337 | ||
@@ -3437,6 +3542,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
3437 | 3542 | ||
3438 | err_exit: | 3543 | err_exit: |
3439 | delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); | 3544 | delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); |
3545 | sysfs_remove_group(&tpacpi_pdev->dev.kobj, | ||
3546 | &adaptive_kbd_attr_group); | ||
3547 | |||
3440 | hotkey_dev_attributes = NULL; | 3548 | hotkey_dev_attributes = NULL; |
3441 | 3549 | ||
3442 | return (res < 0) ? res : 1; | 3550 | return (res < 0) ? res : 1; |
@@ -3449,14 +3557,6 @@ err_exit: | |||
3449 | * Will consider support rest of modes in future. | 3557 | * Will consider support rest of modes in future. |
3450 | * | 3558 | * |
3451 | */ | 3559 | */ |
3452 | enum ADAPTIVE_KEY_MODE { | ||
3453 | HOME_MODE, | ||
3454 | WEB_BROWSER_MODE, | ||
3455 | WEB_CONFERENCE_MODE, | ||
3456 | FUNCTION_MODE, | ||
3457 | LAYFLAT_MODE | ||
3458 | }; | ||
3459 | |||
3460 | static const int adaptive_keyboard_modes[] = { | 3560 | static const int adaptive_keyboard_modes[] = { |
3461 | HOME_MODE, | 3561 | HOME_MODE, |
3462 | /* WEB_BROWSER_MODE = 2, | 3562 | /* WEB_BROWSER_MODE = 2, |
@@ -3466,6 +3566,8 @@ static const int adaptive_keyboard_modes[] = { | |||
3466 | 3566 | ||
3467 | #define DFR_CHANGE_ROW 0x101 | 3567 | #define DFR_CHANGE_ROW 0x101 |
3468 | #define DFR_SHOW_QUICKVIEW_ROW 0x102 | 3568 | #define DFR_SHOW_QUICKVIEW_ROW 0x102 |
3569 | #define FIRST_ADAPTIVE_KEY 0x103 | ||
3570 | #define ADAPTIVE_KEY_OFFSET 0x020 | ||
3469 | 3571 | ||
3470 | /* press Fn key a while second, it will switch to Function Mode. Then | 3572 | /* press Fn key a while second, it will switch to Function Mode. Then |
3471 | * release Fn key, previous mode be restored. | 3573 | * release Fn key, previous mode be restored. |
@@ -3473,6 +3575,32 @@ static const int adaptive_keyboard_modes[] = { | |||
3473 | static bool adaptive_keyboard_mode_is_saved; | 3575 | static bool adaptive_keyboard_mode_is_saved; |
3474 | static int adaptive_keyboard_prev_mode; | 3576 | static int adaptive_keyboard_prev_mode; |
3475 | 3577 | ||
3578 | static int adaptive_keyboard_get_mode(void) | ||
3579 | { | ||
3580 | int mode = 0; | ||
3581 | |||
3582 | if (!acpi_evalf(hkey_handle, &mode, "GTRW", "dd", 0)) { | ||
3583 | pr_err("Cannot read adaptive keyboard mode\n"); | ||
3584 | return -EIO; | ||
3585 | } | ||
3586 | |||
3587 | return mode; | ||
3588 | } | ||
3589 | |||
3590 | static int adaptive_keyboard_set_mode(int new_mode) | ||
3591 | { | ||
3592 | if (new_mode < 0 || | ||
3593 | new_mode > LAYFLAT_MODE) | ||
3594 | return -EINVAL; | ||
3595 | |||
3596 | if (!acpi_evalf(hkey_handle, NULL, "STRW", "vd", new_mode)) { | ||
3597 | pr_err("Cannot set adaptive keyboard mode\n"); | ||
3598 | return -EIO; | ||
3599 | } | ||
3600 | |||
3601 | return 0; | ||
3602 | } | ||
3603 | |||
3476 | static int adaptive_keyboard_get_next_mode(int mode) | 3604 | static int adaptive_keyboard_get_next_mode(int mode) |
3477 | { | 3605 | { |
3478 | size_t i; | 3606 | size_t i; |
@@ -3493,8 +3621,9 @@ static int adaptive_keyboard_get_next_mode(int mode) | |||
3493 | 3621 | ||
3494 | static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode) | 3622 | static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode) |
3495 | { | 3623 | { |
3496 | u32 current_mode = 0; | 3624 | int current_mode = 0; |
3497 | int new_mode = 0; | 3625 | int new_mode = 0; |
3626 | int keycode; | ||
3498 | 3627 | ||
3499 | switch (scancode) { | 3628 | switch (scancode) { |
3500 | case DFR_CHANGE_ROW: | 3629 | case DFR_CHANGE_ROW: |
@@ -3502,43 +3631,51 @@ static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode) | |||
3502 | new_mode = adaptive_keyboard_prev_mode; | 3631 | new_mode = adaptive_keyboard_prev_mode; |
3503 | adaptive_keyboard_mode_is_saved = false; | 3632 | adaptive_keyboard_mode_is_saved = false; |
3504 | } else { | 3633 | } else { |
3505 | if (!acpi_evalf( | 3634 | current_mode = adaptive_keyboard_get_mode(); |
3506 | hkey_handle, ¤t_mode, | 3635 | if (current_mode < 0) |
3507 | "GTRW", "dd", 0)) { | ||
3508 | pr_err("Cannot read adaptive keyboard mode\n"); | ||
3509 | return false; | 3636 | return false; |
3510 | } else { | 3637 | new_mode = adaptive_keyboard_get_next_mode( |
3511 | new_mode = adaptive_keyboard_get_next_mode( | 3638 | current_mode); |
3512 | current_mode); | ||
3513 | } | ||
3514 | } | 3639 | } |
3515 | 3640 | ||
3516 | if (!acpi_evalf(hkey_handle, NULL, "STRW", "vd", new_mode)) { | 3641 | if (adaptive_keyboard_set_mode(new_mode) < 0) |
3517 | pr_err("Cannot set adaptive keyboard mode\n"); | ||
3518 | return false; | 3642 | return false; |
3519 | } | ||
3520 | 3643 | ||
3521 | return true; | 3644 | return true; |
3522 | 3645 | ||
3523 | case DFR_SHOW_QUICKVIEW_ROW: | 3646 | case DFR_SHOW_QUICKVIEW_ROW: |
3524 | if (!acpi_evalf(hkey_handle, | 3647 | current_mode = adaptive_keyboard_get_mode(); |
3525 | &adaptive_keyboard_prev_mode, | 3648 | if (current_mode < 0) |
3526 | "GTRW", "dd", 0)) { | ||
3527 | pr_err("Cannot read adaptive keyboard mode\n"); | ||
3528 | return false; | 3649 | return false; |
3529 | } else { | ||
3530 | adaptive_keyboard_mode_is_saved = true; | ||
3531 | 3650 | ||
3532 | if (!acpi_evalf(hkey_handle, | 3651 | adaptive_keyboard_prev_mode = current_mode; |
3533 | NULL, "STRW", "vd", FUNCTION_MODE)) { | 3652 | adaptive_keyboard_mode_is_saved = true; |
3534 | pr_err("Cannot set adaptive keyboard mode\n"); | 3653 | |
3535 | return false; | 3654 | if (adaptive_keyboard_set_mode (FUNCTION_MODE) < 0) |
3536 | } | 3655 | return false; |
3537 | } | ||
3538 | return true; | 3656 | return true; |
3539 | 3657 | ||
3540 | default: | 3658 | default: |
3541 | return false; | 3659 | if (scancode < FIRST_ADAPTIVE_KEY || |
3660 | scancode >= FIRST_ADAPTIVE_KEY + TPACPI_HOTKEY_MAP_LEN - | ||
3661 | ADAPTIVE_KEY_OFFSET) { | ||
3662 | pr_info("Unhandled adaptive keyboard key: 0x%x\n", | ||
3663 | scancode); | ||
3664 | return false; | ||
3665 | } | ||
3666 | keycode = hotkey_keycode_map[scancode - FIRST_ADAPTIVE_KEY + ADAPTIVE_KEY_OFFSET]; | ||
3667 | if (keycode != KEY_RESERVED) { | ||
3668 | mutex_lock(&tpacpi_inputdev_send_mutex); | ||
3669 | |||
3670 | input_report_key(tpacpi_inputdev, keycode, 1); | ||
3671 | input_sync(tpacpi_inputdev); | ||
3672 | |||
3673 | input_report_key(tpacpi_inputdev, keycode, 0); | ||
3674 | input_sync(tpacpi_inputdev); | ||
3675 | |||
3676 | mutex_unlock(&tpacpi_inputdev_send_mutex); | ||
3677 | } | ||
3678 | return true; | ||
3542 | } | 3679 | } |
3543 | } | 3680 | } |
3544 | 3681 | ||
@@ -3836,28 +3973,21 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
3836 | 3973 | ||
3837 | static void hotkey_suspend(void) | 3974 | static void hotkey_suspend(void) |
3838 | { | 3975 | { |
3839 | int hkeyv; | ||
3840 | |||
3841 | /* Do these on suspend, we get the events on early resume! */ | 3976 | /* Do these on suspend, we get the events on early resume! */ |
3842 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE; | 3977 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE; |
3843 | hotkey_autosleep_ack = 0; | 3978 | hotkey_autosleep_ack = 0; |
3844 | 3979 | ||
3845 | /* save previous mode of adaptive keyboard of X1 Carbon */ | 3980 | /* save previous mode of adaptive keyboard of X1 Carbon */ |
3846 | if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { | 3981 | if (tp_features.has_adaptive_kbd) { |
3847 | if ((hkeyv >> 8) == 2) { | 3982 | if (!acpi_evalf(hkey_handle, &adaptive_keyboard_prev_mode, |
3848 | if (!acpi_evalf(hkey_handle, | 3983 | "GTRW", "dd", 0)) { |
3849 | &adaptive_keyboard_prev_mode, | 3984 | pr_err("Cannot read adaptive keyboard mode.\n"); |
3850 | "GTRW", "dd", 0)) { | ||
3851 | pr_err("Cannot read adaptive keyboard mode.\n"); | ||
3852 | } | ||
3853 | } | 3985 | } |
3854 | } | 3986 | } |
3855 | } | 3987 | } |
3856 | 3988 | ||
3857 | static void hotkey_resume(void) | 3989 | static void hotkey_resume(void) |
3858 | { | 3990 | { |
3859 | int hkeyv; | ||
3860 | |||
3861 | tpacpi_disable_brightness_delay(); | 3991 | tpacpi_disable_brightness_delay(); |
3862 | 3992 | ||
3863 | if (hotkey_status_set(true) < 0 || | 3993 | if (hotkey_status_set(true) < 0 || |
@@ -3872,14 +4002,10 @@ static void hotkey_resume(void) | |||
3872 | hotkey_poll_setup_safe(false); | 4002 | hotkey_poll_setup_safe(false); |
3873 | 4003 | ||
3874 | /* restore previous mode of adapive keyboard of X1 Carbon */ | 4004 | /* restore previous mode of adapive keyboard of X1 Carbon */ |
3875 | if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { | 4005 | if (tp_features.has_adaptive_kbd) { |
3876 | if ((hkeyv >> 8) == 2) { | 4006 | if (!acpi_evalf(hkey_handle, NULL, "STRW", "vd", |
3877 | if (!acpi_evalf(hkey_handle, | 4007 | adaptive_keyboard_prev_mode)) { |
3878 | NULL, | 4008 | pr_err("Cannot set adaptive keyboard mode.\n"); |
3879 | "STRW", "vd", | ||
3880 | adaptive_keyboard_prev_mode)) { | ||
3881 | pr_err("Cannot set adaptive keyboard mode.\n"); | ||
3882 | } | ||
3883 | } | 4009 | } |
3884 | } | 4010 | } |
3885 | } | 4011 | } |
@@ -4079,9 +4205,7 @@ static ssize_t bluetooth_enable_store(struct device *dev, | |||
4079 | attr, buf, count); | 4205 | attr, buf, count); |
4080 | } | 4206 | } |
4081 | 4207 | ||
4082 | static struct device_attribute dev_attr_bluetooth_enable = | 4208 | static DEVICE_ATTR_RW(bluetooth_enable); |
4083 | __ATTR(bluetooth_enable, S_IWUSR | S_IRUGO, | ||
4084 | bluetooth_enable_show, bluetooth_enable_store); | ||
4085 | 4209 | ||
4086 | /* --------------------------------------------------------------------- */ | 4210 | /* --------------------------------------------------------------------- */ |
4087 | 4211 | ||
@@ -4269,9 +4393,7 @@ static ssize_t wan_enable_store(struct device *dev, | |||
4269 | attr, buf, count); | 4393 | attr, buf, count); |
4270 | } | 4394 | } |
4271 | 4395 | ||
4272 | static struct device_attribute dev_attr_wan_enable = | 4396 | static DEVICE_ATTR_RW(wan_enable); |
4273 | __ATTR(wwan_enable, S_IWUSR | S_IRUGO, | ||
4274 | wan_enable_show, wan_enable_store); | ||
4275 | 4397 | ||
4276 | /* --------------------------------------------------------------------- */ | 4398 | /* --------------------------------------------------------------------- */ |
4277 | 4399 | ||
@@ -5048,8 +5170,7 @@ static ssize_t cmos_command_store(struct device *dev, | |||
5048 | return (res) ? res : count; | 5170 | return (res) ? res : count; |
5049 | } | 5171 | } |
5050 | 5172 | ||
5051 | static struct device_attribute dev_attr_cmos_command = | 5173 | static DEVICE_ATTR_WO(cmos_command); |
5052 | __ATTR(cmos_command, S_IWUSR, NULL, cmos_command_store); | ||
5053 | 5174 | ||
5054 | /* --------------------------------------------------------------------- */ | 5175 | /* --------------------------------------------------------------------- */ |
5055 | 5176 | ||
@@ -8017,9 +8138,7 @@ static ssize_t fan_pwm1_enable_store(struct device *dev, | |||
8017 | return count; | 8138 | return count; |
8018 | } | 8139 | } |
8019 | 8140 | ||
8020 | static struct device_attribute dev_attr_fan_pwm1_enable = | 8141 | static DEVICE_ATTR_RW(fan_pwm1_enable); |
8021 | __ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | ||
8022 | fan_pwm1_enable_show, fan_pwm1_enable_store); | ||
8023 | 8142 | ||
8024 | /* sysfs fan pwm1 ------------------------------------------------------ */ | 8143 | /* sysfs fan pwm1 ------------------------------------------------------ */ |
8025 | static ssize_t fan_pwm1_show(struct device *dev, | 8144 | static ssize_t fan_pwm1_show(struct device *dev, |
@@ -8079,9 +8198,7 @@ static ssize_t fan_pwm1_store(struct device *dev, | |||
8079 | return (rc) ? rc : count; | 8198 | return (rc) ? rc : count; |
8080 | } | 8199 | } |
8081 | 8200 | ||
8082 | static struct device_attribute dev_attr_fan_pwm1 = | 8201 | static DEVICE_ATTR_RW(fan_pwm1); |
8083 | __ATTR(pwm1, S_IWUSR | S_IRUGO, | ||
8084 | fan_pwm1_show, fan_pwm1_store); | ||
8085 | 8202 | ||
8086 | /* sysfs fan fan1_input ------------------------------------------------ */ | 8203 | /* sysfs fan fan1_input ------------------------------------------------ */ |
8087 | static ssize_t fan_fan1_input_show(struct device *dev, | 8204 | static ssize_t fan_fan1_input_show(struct device *dev, |
@@ -8098,9 +8215,7 @@ static ssize_t fan_fan1_input_show(struct device *dev, | |||
8098 | return snprintf(buf, PAGE_SIZE, "%u\n", speed); | 8215 | return snprintf(buf, PAGE_SIZE, "%u\n", speed); |
8099 | } | 8216 | } |
8100 | 8217 | ||
8101 | static struct device_attribute dev_attr_fan_fan1_input = | 8218 | static DEVICE_ATTR_RO(fan_fan1_input); |
8102 | __ATTR(fan1_input, S_IRUGO, | ||
8103 | fan_fan1_input_show, NULL); | ||
8104 | 8219 | ||
8105 | /* sysfs fan fan2_input ------------------------------------------------ */ | 8220 | /* sysfs fan fan2_input ------------------------------------------------ */ |
8106 | static ssize_t fan_fan2_input_show(struct device *dev, | 8221 | static ssize_t fan_fan2_input_show(struct device *dev, |
@@ -8117,9 +8232,7 @@ static ssize_t fan_fan2_input_show(struct device *dev, | |||
8117 | return snprintf(buf, PAGE_SIZE, "%u\n", speed); | 8232 | return snprintf(buf, PAGE_SIZE, "%u\n", speed); |
8118 | } | 8233 | } |
8119 | 8234 | ||
8120 | static struct device_attribute dev_attr_fan_fan2_input = | 8235 | static DEVICE_ATTR_RO(fan_fan2_input); |
8121 | __ATTR(fan2_input, S_IRUGO, | ||
8122 | fan_fan2_input_show, NULL); | ||
8123 | 8236 | ||
8124 | /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ | 8237 | /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ |
8125 | static ssize_t fan_fan_watchdog_show(struct device_driver *drv, | 8238 | static ssize_t fan_fan_watchdog_show(struct device_driver *drv, |
@@ -8735,8 +8848,7 @@ static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev, | |||
8735 | return snprintf(buf, PAGE_SIZE, "%s\n", TPACPI_NAME); | 8848 | return snprintf(buf, PAGE_SIZE, "%s\n", TPACPI_NAME); |
8736 | } | 8849 | } |
8737 | 8850 | ||
8738 | static struct device_attribute dev_attr_thinkpad_acpi_pdev_name = | 8851 | static DEVICE_ATTR_RO(thinkpad_acpi_pdev_name); |
8739 | __ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL); | ||
8740 | 8852 | ||
8741 | /* --------------------------------------------------------------------- */ | 8853 | /* --------------------------------------------------------------------- */ |
8742 | 8854 | ||
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index dbcb7a8915b8..9956b9902bb4 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/acpi.h> | 51 | #include <linux/acpi.h> |
52 | #include <linux/dmi.h> | 52 | #include <linux/dmi.h> |
53 | #include <linux/uaccess.h> | 53 | #include <linux/uaccess.h> |
54 | #include <acpi/video.h> | ||
54 | 55 | ||
55 | MODULE_AUTHOR("John Belmonte"); | 56 | MODULE_AUTHOR("John Belmonte"); |
56 | MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver"); | 57 | MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver"); |
@@ -116,6 +117,7 @@ MODULE_LICENSE("GPL"); | |||
116 | #define HCI_KBD_ILLUMINATION 0x0095 | 117 | #define HCI_KBD_ILLUMINATION 0x0095 |
117 | #define HCI_ECO_MODE 0x0097 | 118 | #define HCI_ECO_MODE 0x0097 |
118 | #define HCI_ACCELEROMETER2 0x00a6 | 119 | #define HCI_ACCELEROMETER2 0x00a6 |
120 | #define HCI_SYSTEM_INFO 0xc000 | ||
119 | #define SCI_PANEL_POWER_ON 0x010d | 121 | #define SCI_PANEL_POWER_ON 0x010d |
120 | #define SCI_ILLUMINATION 0x014e | 122 | #define SCI_ILLUMINATION 0x014e |
121 | #define SCI_USB_SLEEP_CHARGE 0x0150 | 123 | #define SCI_USB_SLEEP_CHARGE 0x0150 |
@@ -129,10 +131,13 @@ MODULE_LICENSE("GPL"); | |||
129 | #define HCI_ACCEL_MASK 0x7fff | 131 | #define HCI_ACCEL_MASK 0x7fff |
130 | #define HCI_HOTKEY_DISABLE 0x0b | 132 | #define HCI_HOTKEY_DISABLE 0x0b |
131 | #define HCI_HOTKEY_ENABLE 0x09 | 133 | #define HCI_HOTKEY_ENABLE 0x09 |
134 | #define HCI_HOTKEY_SPECIAL_FUNCTIONS 0x10 | ||
132 | #define HCI_LCD_BRIGHTNESS_BITS 3 | 135 | #define HCI_LCD_BRIGHTNESS_BITS 3 |
133 | #define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS) | 136 | #define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS) |
134 | #define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS) | 137 | #define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS) |
135 | #define HCI_MISC_SHIFT 0x10 | 138 | #define HCI_MISC_SHIFT 0x10 |
139 | #define HCI_SYSTEM_TYPE1 0x10 | ||
140 | #define HCI_SYSTEM_TYPE2 0x11 | ||
136 | #define HCI_VIDEO_OUT_LCD 0x1 | 141 | #define HCI_VIDEO_OUT_LCD 0x1 |
137 | #define HCI_VIDEO_OUT_CRT 0x2 | 142 | #define HCI_VIDEO_OUT_CRT 0x2 |
138 | #define HCI_VIDEO_OUT_TV 0x4 | 143 | #define HCI_VIDEO_OUT_TV 0x4 |
@@ -147,9 +152,10 @@ MODULE_LICENSE("GPL"); | |||
147 | #define SCI_KBD_MODE_OFF 0x10 | 152 | #define SCI_KBD_MODE_OFF 0x10 |
148 | #define SCI_KBD_TIME_MAX 0x3c001a | 153 | #define SCI_KBD_TIME_MAX 0x3c001a |
149 | #define SCI_USB_CHARGE_MODE_MASK 0xff | 154 | #define SCI_USB_CHARGE_MODE_MASK 0xff |
150 | #define SCI_USB_CHARGE_DISABLED 0x30000 | 155 | #define SCI_USB_CHARGE_DISABLED 0x00 |
151 | #define SCI_USB_CHARGE_ALTERNATE 0x30009 | 156 | #define SCI_USB_CHARGE_ALTERNATE 0x09 |
152 | #define SCI_USB_CHARGE_AUTO 0x30021 | 157 | #define SCI_USB_CHARGE_TYPICAL 0x11 |
158 | #define SCI_USB_CHARGE_AUTO 0x21 | ||
153 | #define SCI_USB_CHARGE_BAT_MASK 0x7 | 159 | #define SCI_USB_CHARGE_BAT_MASK 0x7 |
154 | #define SCI_USB_CHARGE_BAT_LVL_OFF 0x1 | 160 | #define SCI_USB_CHARGE_BAT_LVL_OFF 0x1 |
155 | #define SCI_USB_CHARGE_BAT_LVL_ON 0x4 | 161 | #define SCI_USB_CHARGE_BAT_LVL_ON 0x4 |
@@ -174,6 +180,8 @@ struct toshiba_acpi_dev { | |||
174 | int kbd_mode; | 180 | int kbd_mode; |
175 | int kbd_time; | 181 | int kbd_time; |
176 | int usbsc_bat_level; | 182 | int usbsc_bat_level; |
183 | int usbsc_mode_base; | ||
184 | int hotkey_event_type; | ||
177 | 185 | ||
178 | unsigned int illumination_supported:1; | 186 | unsigned int illumination_supported:1; |
179 | unsigned int video_supported:1; | 187 | unsigned int video_supported:1; |
@@ -243,29 +251,6 @@ static const struct key_entry toshiba_acpi_keymap[] = { | |||
243 | { KE_END, 0 }, | 251 | { KE_END, 0 }, |
244 | }; | 252 | }; |
245 | 253 | ||
246 | /* alternative keymap */ | ||
247 | static const struct dmi_system_id toshiba_alt_keymap_dmi[] = { | ||
248 | { | ||
249 | .matches = { | ||
250 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
251 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), | ||
252 | }, | ||
253 | }, | ||
254 | { | ||
255 | .matches = { | ||
256 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
257 | DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"), | ||
258 | }, | ||
259 | }, | ||
260 | { | ||
261 | .matches = { | ||
262 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
263 | DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A50-A"), | ||
264 | }, | ||
265 | }, | ||
266 | {} | ||
267 | }; | ||
268 | |||
269 | static const struct key_entry toshiba_acpi_alt_keymap[] = { | 254 | static const struct key_entry toshiba_acpi_alt_keymap[] = { |
270 | { KE_KEY, 0x157, { KEY_MUTE } }, | 255 | { KE_KEY, 0x157, { KEY_MUTE } }, |
271 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, | 256 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, |
@@ -281,6 +266,14 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = { | |||
281 | }; | 266 | }; |
282 | 267 | ||
283 | /* | 268 | /* |
269 | * List of models which have a broken acpi-video backlight interface and thus | ||
270 | * need to use the toshiba (vendor) interface instead. | ||
271 | */ | ||
272 | static const struct dmi_system_id toshiba_vendor_backlight_dmi[] = { | ||
273 | {} | ||
274 | }; | ||
275 | |||
276 | /* | ||
284 | * Utility | 277 | * Utility |
285 | */ | 278 | */ |
286 | 279 | ||
@@ -819,6 +812,54 @@ static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev, | |||
819 | } | 812 | } |
820 | 813 | ||
821 | /* Sleep (Charge and Music) utilities support */ | 814 | /* Sleep (Charge and Music) utilities support */ |
815 | static void toshiba_usb_sleep_charge_available(struct toshiba_acpi_dev *dev) | ||
816 | { | ||
817 | u32 in[TCI_WORDS] = { SCI_GET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 }; | ||
818 | u32 out[TCI_WORDS]; | ||
819 | acpi_status status; | ||
820 | |||
821 | /* Set the feature to "not supported" in case of error */ | ||
822 | dev->usb_sleep_charge_supported = 0; | ||
823 | |||
824 | if (!sci_open(dev)) | ||
825 | return; | ||
826 | |||
827 | status = tci_raw(dev, in, out); | ||
828 | if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { | ||
829 | pr_err("ACPI call to get USB Sleep and Charge mode failed\n"); | ||
830 | sci_close(dev); | ||
831 | return; | ||
832 | } else if (out[0] == TOS_NOT_SUPPORTED) { | ||
833 | pr_info("USB Sleep and Charge not supported\n"); | ||
834 | sci_close(dev); | ||
835 | return; | ||
836 | } else if (out[0] == TOS_SUCCESS) { | ||
837 | dev->usbsc_mode_base = out[4]; | ||
838 | } | ||
839 | |||
840 | in[5] = SCI_USB_CHARGE_BAT_LVL; | ||
841 | status = tci_raw(dev, in, out); | ||
842 | if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { | ||
843 | pr_err("ACPI call to get USB Sleep and Charge mode failed\n"); | ||
844 | sci_close(dev); | ||
845 | return; | ||
846 | } else if (out[0] == TOS_NOT_SUPPORTED) { | ||
847 | pr_info("USB Sleep and Charge not supported\n"); | ||
848 | sci_close(dev); | ||
849 | return; | ||
850 | } else if (out[0] == TOS_SUCCESS) { | ||
851 | dev->usbsc_bat_level = out[2]; | ||
852 | /* | ||
853 | * If we reach this point, it means that the laptop has support | ||
854 | * for this feature and all values are initialized. | ||
855 | * Set it as supported. | ||
856 | */ | ||
857 | dev->usb_sleep_charge_supported = 1; | ||
858 | } | ||
859 | |||
860 | sci_close(dev); | ||
861 | } | ||
862 | |||
822 | static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev, | 863 | static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev, |
823 | u32 *mode) | 864 | u32 *mode) |
824 | { | 865 | { |
@@ -934,11 +975,11 @@ static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev, | |||
934 | status = tci_raw(dev, in, out); | 975 | status = tci_raw(dev, in, out); |
935 | sci_close(dev); | 976 | sci_close(dev); |
936 | if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { | 977 | if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { |
937 | pr_err("ACPI call to get USB S&C battery level failed\n"); | 978 | pr_err("ACPI call to get USB Rapid Charge failed\n"); |
938 | return -EIO; | 979 | return -EIO; |
939 | } else if (out[0] == TOS_NOT_SUPPORTED || | 980 | } else if (out[0] == TOS_NOT_SUPPORTED || |
940 | out[0] == TOS_INPUT_DATA_ERROR) { | 981 | out[0] == TOS_INPUT_DATA_ERROR) { |
941 | pr_info("USB Sleep and Charge not supported\n"); | 982 | pr_info("USB Rapid Charge not supported\n"); |
942 | return -ENODEV; | 983 | return -ENODEV; |
943 | } | 984 | } |
944 | 985 | ||
@@ -962,10 +1003,10 @@ static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev, | |||
962 | status = tci_raw(dev, in, out); | 1003 | status = tci_raw(dev, in, out); |
963 | sci_close(dev); | 1004 | sci_close(dev); |
964 | if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { | 1005 | if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { |
965 | pr_err("ACPI call to set USB S&C battery level failed\n"); | 1006 | pr_err("ACPI call to set USB Rapid Charge failed\n"); |
966 | return -EIO; | 1007 | return -EIO; |
967 | } else if (out[0] == TOS_NOT_SUPPORTED) { | 1008 | } else if (out[0] == TOS_NOT_SUPPORTED) { |
968 | pr_info("USB Sleep and Charge not supported\n"); | 1009 | pr_info("USB Rapid Charge not supported\n"); |
969 | return -ENODEV; | 1010 | return -ENODEV; |
970 | } else if (out[0] == TOS_INPUT_DATA_ERROR) { | 1011 | } else if (out[0] == TOS_INPUT_DATA_ERROR) { |
971 | return -EIO; | 1012 | return -EIO; |
@@ -984,10 +1025,10 @@ static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state) | |||
984 | result = sci_read(dev, SCI_USB_SLEEP_MUSIC, state); | 1025 | result = sci_read(dev, SCI_USB_SLEEP_MUSIC, state); |
985 | sci_close(dev); | 1026 | sci_close(dev); |
986 | if (result == TOS_FAILURE) { | 1027 | if (result == TOS_FAILURE) { |
987 | pr_err("ACPI call to set USB S&C mode failed\n"); | 1028 | pr_err("ACPI call to get Sleep and Music failed\n"); |
988 | return -EIO; | 1029 | return -EIO; |
989 | } else if (result == TOS_NOT_SUPPORTED) { | 1030 | } else if (result == TOS_NOT_SUPPORTED) { |
990 | pr_info("USB Sleep and Charge not supported\n"); | 1031 | pr_info("Sleep and Music not supported\n"); |
991 | return -ENODEV; | 1032 | return -ENODEV; |
992 | } else if (result == TOS_INPUT_DATA_ERROR) { | 1033 | } else if (result == TOS_INPUT_DATA_ERROR) { |
993 | return -EIO; | 1034 | return -EIO; |
@@ -1006,10 +1047,10 @@ static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state) | |||
1006 | result = sci_write(dev, SCI_USB_SLEEP_MUSIC, state); | 1047 | result = sci_write(dev, SCI_USB_SLEEP_MUSIC, state); |
1007 | sci_close(dev); | 1048 | sci_close(dev); |
1008 | if (result == TOS_FAILURE) { | 1049 | if (result == TOS_FAILURE) { |
1009 | pr_err("ACPI call to set USB S&C mode failed\n"); | 1050 | pr_err("ACPI call to set Sleep and Music failed\n"); |
1010 | return -EIO; | 1051 | return -EIO; |
1011 | } else if (result == TOS_NOT_SUPPORTED) { | 1052 | } else if (result == TOS_NOT_SUPPORTED) { |
1012 | pr_info("USB Sleep and Charge not supported\n"); | 1053 | pr_info("Sleep and Music not supported\n"); |
1013 | return -ENODEV; | 1054 | return -ENODEV; |
1014 | } else if (result == TOS_INPUT_DATA_ERROR) { | 1055 | } else if (result == TOS_INPUT_DATA_ERROR) { |
1015 | return -EIO; | 1056 | return -EIO; |
@@ -1149,6 +1190,28 @@ static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state) | |||
1149 | return 0; | 1190 | return 0; |
1150 | } | 1191 | } |
1151 | 1192 | ||
1193 | /* Hotkey Event type */ | ||
1194 | static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev, | ||
1195 | u32 *type) | ||
1196 | { | ||
1197 | u32 val1 = 0x03; | ||
1198 | u32 val2 = 0; | ||
1199 | u32 result; | ||
1200 | |||
1201 | result = hci_read2(dev, HCI_SYSTEM_INFO, &val1, &val2); | ||
1202 | if (result == TOS_FAILURE) { | ||
1203 | pr_err("ACPI call to get System type failed\n"); | ||
1204 | return -EIO; | ||
1205 | } else if (result == TOS_NOT_SUPPORTED) { | ||
1206 | pr_info("System type not supported\n"); | ||
1207 | return -ENODEV; | ||
1208 | } | ||
1209 | |||
1210 | *type = val2; | ||
1211 | |||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1152 | /* Bluetooth rfkill handlers */ | 1215 | /* Bluetooth rfkill handlers */ |
1153 | 1216 | ||
1154 | static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) | 1217 | static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) |
@@ -1973,17 +2036,21 @@ static ssize_t usb_sleep_charge_store(struct device *dev, | |||
1973 | * 0 - Disabled | 2036 | * 0 - Disabled |
1974 | * 1 - Alternate (Non USB conformant devices that require more power) | 2037 | * 1 - Alternate (Non USB conformant devices that require more power) |
1975 | * 2 - Auto (USB conformant devices) | 2038 | * 2 - Auto (USB conformant devices) |
2039 | * 3 - Typical | ||
1976 | */ | 2040 | */ |
1977 | if (state != 0 && state != 1 && state != 2) | 2041 | if (state != 0 && state != 1 && state != 2 && state != 3) |
1978 | return -EINVAL; | 2042 | return -EINVAL; |
1979 | 2043 | ||
1980 | /* Set the USB charging mode to internal value */ | 2044 | /* Set the USB charging mode to internal value */ |
2045 | mode = toshiba->usbsc_mode_base; | ||
1981 | if (state == 0) | 2046 | if (state == 0) |
1982 | mode = SCI_USB_CHARGE_DISABLED; | 2047 | mode |= SCI_USB_CHARGE_DISABLED; |
1983 | else if (state == 1) | 2048 | else if (state == 1) |
1984 | mode = SCI_USB_CHARGE_ALTERNATE; | 2049 | mode |= SCI_USB_CHARGE_ALTERNATE; |
1985 | else if (state == 2) | 2050 | else if (state == 2) |
1986 | mode = SCI_USB_CHARGE_AUTO; | 2051 | mode |= SCI_USB_CHARGE_AUTO; |
2052 | else if (state == 3) | ||
2053 | mode |= SCI_USB_CHARGE_TYPICAL; | ||
1987 | 2054 | ||
1988 | ret = toshiba_usb_sleep_charge_set(toshiba, mode); | 2055 | ret = toshiba_usb_sleep_charge_set(toshiba, mode); |
1989 | if (ret) | 2056 | if (ret) |
@@ -2333,6 +2400,20 @@ static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev) | |||
2333 | return 0; | 2400 | return 0; |
2334 | } | 2401 | } |
2335 | 2402 | ||
2403 | static void toshiba_acpi_enable_special_functions(struct toshiba_acpi_dev *dev) | ||
2404 | { | ||
2405 | u32 result; | ||
2406 | |||
2407 | /* | ||
2408 | * Re-activate the hotkeys, but this time, we are using the | ||
2409 | * "Special Functions" mode. | ||
2410 | */ | ||
2411 | result = hci_write1(dev, HCI_HOTKEY_EVENT, | ||
2412 | HCI_HOTKEY_SPECIAL_FUNCTIONS); | ||
2413 | if (result != TOS_SUCCESS) | ||
2414 | pr_err("Could not enable the Special Function mode\n"); | ||
2415 | } | ||
2416 | |||
2336 | static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str, | 2417 | static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str, |
2337 | struct serio *port) | 2418 | struct serio *port) |
2338 | { | 2419 | { |
@@ -2434,10 +2515,22 @@ static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev) | |||
2434 | 2515 | ||
2435 | static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) | 2516 | static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) |
2436 | { | 2517 | { |
2518 | const struct key_entry *keymap = toshiba_acpi_keymap; | ||
2437 | acpi_handle ec_handle; | 2519 | acpi_handle ec_handle; |
2438 | int error; | 2520 | u32 events_type; |
2439 | u32 hci_result; | 2521 | u32 hci_result; |
2440 | const struct key_entry *keymap = toshiba_acpi_keymap; | 2522 | int error; |
2523 | |||
2524 | error = toshiba_acpi_enable_hotkeys(dev); | ||
2525 | if (error) | ||
2526 | return error; | ||
2527 | |||
2528 | error = toshiba_hotkey_event_type_get(dev, &events_type); | ||
2529 | if (error) { | ||
2530 | pr_err("Unable to query Hotkey Event Type\n"); | ||
2531 | return error; | ||
2532 | } | ||
2533 | dev->hotkey_event_type = events_type; | ||
2441 | 2534 | ||
2442 | dev->hotkey_dev = input_allocate_device(); | 2535 | dev->hotkey_dev = input_allocate_device(); |
2443 | if (!dev->hotkey_dev) | 2536 | if (!dev->hotkey_dev) |
@@ -2447,8 +2540,14 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) | |||
2447 | dev->hotkey_dev->phys = "toshiba_acpi/input0"; | 2540 | dev->hotkey_dev->phys = "toshiba_acpi/input0"; |
2448 | dev->hotkey_dev->id.bustype = BUS_HOST; | 2541 | dev->hotkey_dev->id.bustype = BUS_HOST; |
2449 | 2542 | ||
2450 | if (dmi_check_system(toshiba_alt_keymap_dmi)) | 2543 | if (events_type == HCI_SYSTEM_TYPE1 || |
2544 | !dev->kbd_function_keys_supported) | ||
2545 | keymap = toshiba_acpi_keymap; | ||
2546 | else if (events_type == HCI_SYSTEM_TYPE2 || | ||
2547 | dev->kbd_function_keys_supported) | ||
2451 | keymap = toshiba_acpi_alt_keymap; | 2548 | keymap = toshiba_acpi_alt_keymap; |
2549 | else | ||
2550 | pr_info("Unknown event type received %x\n", events_type); | ||
2452 | error = sparse_keymap_setup(dev->hotkey_dev, keymap, NULL); | 2551 | error = sparse_keymap_setup(dev->hotkey_dev, keymap, NULL); |
2453 | if (error) | 2552 | if (error) |
2454 | goto err_free_dev; | 2553 | goto err_free_dev; |
@@ -2490,12 +2589,6 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) | |||
2490 | goto err_remove_filter; | 2589 | goto err_remove_filter; |
2491 | } | 2590 | } |
2492 | 2591 | ||
2493 | error = toshiba_acpi_enable_hotkeys(dev); | ||
2494 | if (error) { | ||
2495 | pr_info("Unable to enable hotkeys\n"); | ||
2496 | goto err_remove_filter; | ||
2497 | } | ||
2498 | |||
2499 | error = input_register_device(dev->hotkey_dev); | 2592 | error = input_register_device(dev->hotkey_dev); |
2500 | if (error) { | 2593 | if (error) { |
2501 | pr_info("Unable to register input device\n"); | 2594 | pr_info("Unable to register input device\n"); |
@@ -2541,6 +2634,20 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) | |||
2541 | ret = get_tr_backlight_status(dev, &enabled); | 2634 | ret = get_tr_backlight_status(dev, &enabled); |
2542 | dev->tr_backlight_supported = !ret; | 2635 | dev->tr_backlight_supported = !ret; |
2543 | 2636 | ||
2637 | /* | ||
2638 | * Tell acpi-video-detect code to prefer vendor backlight on all | ||
2639 | * systems with transflective backlight and on dmi matched systems. | ||
2640 | */ | ||
2641 | if (dev->tr_backlight_supported || | ||
2642 | dmi_check_system(toshiba_vendor_backlight_dmi)) | ||
2643 | acpi_video_dmi_promote_vendor(); | ||
2644 | |||
2645 | if (acpi_video_backlight_support()) | ||
2646 | return 0; | ||
2647 | |||
2648 | /* acpi-video may have loaded before we called dmi_promote_vendor() */ | ||
2649 | acpi_video_unregister_backlight(); | ||
2650 | |||
2544 | memset(&props, 0, sizeof(props)); | 2651 | memset(&props, 0, sizeof(props)); |
2545 | props.type = BACKLIGHT_PLATFORM; | 2652 | props.type = BACKLIGHT_PLATFORM; |
2546 | props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; | 2653 | props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; |
@@ -2624,6 +2731,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
2624 | { | 2731 | { |
2625 | struct toshiba_acpi_dev *dev; | 2732 | struct toshiba_acpi_dev *dev; |
2626 | const char *hci_method; | 2733 | const char *hci_method; |
2734 | u32 special_functions; | ||
2627 | u32 dummy; | 2735 | u32 dummy; |
2628 | bool bt_present; | 2736 | bool bt_present; |
2629 | int ret = 0; | 2737 | int ret = 0; |
@@ -2648,6 +2756,16 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
2648 | acpi_dev->driver_data = dev; | 2756 | acpi_dev->driver_data = dev; |
2649 | dev_set_drvdata(&acpi_dev->dev, dev); | 2757 | dev_set_drvdata(&acpi_dev->dev, dev); |
2650 | 2758 | ||
2759 | /* Query the BIOS for supported features */ | ||
2760 | |||
2761 | /* | ||
2762 | * The "Special Functions" are always supported by the laptops | ||
2763 | * with the new keyboard layout, query for its presence to help | ||
2764 | * determine the keymap layout to use. | ||
2765 | */ | ||
2766 | ret = toshiba_function_keys_get(dev, &special_functions); | ||
2767 | dev->kbd_function_keys_supported = !ret; | ||
2768 | |||
2651 | if (toshiba_acpi_setup_keyboard(dev)) | 2769 | if (toshiba_acpi_setup_keyboard(dev)) |
2652 | pr_info("Unable to activate hotkeys\n"); | 2770 | pr_info("Unable to activate hotkeys\n"); |
2653 | 2771 | ||
@@ -2716,8 +2834,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
2716 | ret = toshiba_accelerometer_supported(dev); | 2834 | ret = toshiba_accelerometer_supported(dev); |
2717 | dev->accelerometer_supported = !ret; | 2835 | dev->accelerometer_supported = !ret; |
2718 | 2836 | ||
2719 | ret = toshiba_usb_sleep_charge_get(dev, &dummy); | 2837 | toshiba_usb_sleep_charge_available(dev); |
2720 | dev->usb_sleep_charge_supported = !ret; | ||
2721 | 2838 | ||
2722 | ret = toshiba_usb_rapid_charge_get(dev, &dummy); | 2839 | ret = toshiba_usb_rapid_charge_get(dev, &dummy); |
2723 | dev->usb_rapid_charge_supported = !ret; | 2840 | dev->usb_rapid_charge_supported = !ret; |
@@ -2725,23 +2842,25 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
2725 | ret = toshiba_usb_sleep_music_get(dev, &dummy); | 2842 | ret = toshiba_usb_sleep_music_get(dev, &dummy); |
2726 | dev->usb_sleep_music_supported = !ret; | 2843 | dev->usb_sleep_music_supported = !ret; |
2727 | 2844 | ||
2728 | ret = toshiba_function_keys_get(dev, &dummy); | ||
2729 | dev->kbd_function_keys_supported = !ret; | ||
2730 | |||
2731 | ret = toshiba_panel_power_on_get(dev, &dummy); | 2845 | ret = toshiba_panel_power_on_get(dev, &dummy); |
2732 | dev->panel_power_on_supported = !ret; | 2846 | dev->panel_power_on_supported = !ret; |
2733 | 2847 | ||
2734 | ret = toshiba_usb_three_get(dev, &dummy); | 2848 | ret = toshiba_usb_three_get(dev, &dummy); |
2735 | dev->usb_three_supported = !ret; | 2849 | dev->usb_three_supported = !ret; |
2736 | 2850 | ||
2737 | /* Determine whether or not BIOS supports fan and video interfaces */ | ||
2738 | |||
2739 | ret = get_video_status(dev, &dummy); | 2851 | ret = get_video_status(dev, &dummy); |
2740 | dev->video_supported = !ret; | 2852 | dev->video_supported = !ret; |
2741 | 2853 | ||
2742 | ret = get_fan_status(dev, &dummy); | 2854 | ret = get_fan_status(dev, &dummy); |
2743 | dev->fan_supported = !ret; | 2855 | dev->fan_supported = !ret; |
2744 | 2856 | ||
2857 | /* | ||
2858 | * Enable the "Special Functions" mode only if they are | ||
2859 | * supported and if they are activated. | ||
2860 | */ | ||
2861 | if (dev->kbd_function_keys_supported && special_functions) | ||
2862 | toshiba_acpi_enable_special_functions(dev); | ||
2863 | |||
2745 | ret = sysfs_create_group(&dev->acpi_dev->dev.kobj, | 2864 | ret = sysfs_create_group(&dev->acpi_dev->dev.kobj, |
2746 | &toshiba_attr_group); | 2865 | &toshiba_attr_group); |
2747 | if (ret) { | 2866 | if (ret) { |
@@ -2770,6 +2889,21 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) | |||
2770 | case 0x80: /* Hotkeys and some system events */ | 2889 | case 0x80: /* Hotkeys and some system events */ |
2771 | toshiba_acpi_process_hotkeys(dev); | 2890 | toshiba_acpi_process_hotkeys(dev); |
2772 | break; | 2891 | break; |
2892 | case 0x81: /* Dock events */ | ||
2893 | case 0x82: | ||
2894 | case 0x83: | ||
2895 | pr_info("Dock event received %x\n", event); | ||
2896 | break; | ||
2897 | case 0x88: /* Thermal events */ | ||
2898 | pr_info("Thermal event received\n"); | ||
2899 | break; | ||
2900 | case 0x8f: /* LID closed */ | ||
2901 | case 0x90: /* LID is closed and Dock has been ejected */ | ||
2902 | break; | ||
2903 | case 0x8c: /* SATA power events */ | ||
2904 | case 0x8b: | ||
2905 | pr_info("SATA power event received %x\n", event); | ||
2906 | break; | ||
2773 | case 0x92: /* Keyboard backlight mode changed */ | 2907 | case 0x92: /* Keyboard backlight mode changed */ |
2774 | /* Update sysfs entries */ | 2908 | /* Update sysfs entries */ |
2775 | ret = sysfs_update_group(&acpi_dev->dev.kobj, | 2909 | ret = sysfs_update_group(&acpi_dev->dev.kobj, |
@@ -2777,17 +2911,19 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) | |||
2777 | if (ret) | 2911 | if (ret) |
2778 | pr_err("Unable to update sysfs entries\n"); | 2912 | pr_err("Unable to update sysfs entries\n"); |
2779 | break; | 2913 | break; |
2780 | case 0x81: /* Unknown */ | 2914 | case 0x85: /* Unknown */ |
2781 | case 0x82: /* Unknown */ | 2915 | case 0x8d: /* Unknown */ |
2782 | case 0x83: /* Unknown */ | ||
2783 | case 0x8c: /* Unknown */ | ||
2784 | case 0x8e: /* Unknown */ | 2916 | case 0x8e: /* Unknown */ |
2785 | case 0x8f: /* Unknown */ | 2917 | case 0x94: /* Unknown */ |
2786 | case 0x90: /* Unknown */ | 2918 | case 0x95: /* Unknown */ |
2787 | default: | 2919 | default: |
2788 | pr_info("Unknown event received %x\n", event); | 2920 | pr_info("Unknown event received %x\n", event); |
2789 | break; | 2921 | break; |
2790 | } | 2922 | } |
2923 | |||
2924 | acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class, | ||
2925 | dev_name(&acpi_dev->dev), | ||
2926 | event, 0); | ||
2791 | } | 2927 | } |
2792 | 2928 | ||
2793 | #ifdef CONFIG_PM_SLEEP | 2929 | #ifdef CONFIG_PM_SLEEP |
diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index 2cb1ea62b4a7..249800763362 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Toshiba Bluetooth Enable Driver | 2 | * Toshiba Bluetooth Enable Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com> | 4 | * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com> |
5 | * Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com> | ||
5 | * | 6 | * |
6 | * Thanks to Matthew Garrett for background info on ACPI innards which | 7 | * Thanks to Matthew Garrett for background info on ACPI innards which |
7 | * normal people aren't meant to understand :-) | 8 | * normal people aren't meant to understand :-) |
@@ -25,6 +26,10 @@ | |||
25 | #include <linux/types.h> | 26 | #include <linux/types.h> |
26 | #include <linux/acpi.h> | 27 | #include <linux/acpi.h> |
27 | 28 | ||
29 | #define BT_KILLSWITCH_MASK 0x01 | ||
30 | #define BT_PLUGGED_MASK 0x40 | ||
31 | #define BT_POWER_MASK 0x80 | ||
32 | |||
28 | MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>"); | 33 | MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>"); |
29 | MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver"); | 34 | MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver"); |
30 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
@@ -57,32 +62,107 @@ static struct acpi_driver toshiba_bt_rfkill_driver = { | |||
57 | .drv.pm = &toshiba_bt_pm, | 62 | .drv.pm = &toshiba_bt_pm, |
58 | }; | 63 | }; |
59 | 64 | ||
65 | static int toshiba_bluetooth_present(acpi_handle handle) | ||
66 | { | ||
67 | acpi_status result; | ||
68 | u64 bt_present; | ||
69 | |||
70 | /* | ||
71 | * Some Toshiba laptops may have a fake TOS6205 device in | ||
72 | * their ACPI BIOS, so query the _STA method to see if there | ||
73 | * is really anything there. | ||
74 | */ | ||
75 | result = acpi_evaluate_integer(handle, "_STA", NULL, &bt_present); | ||
76 | if (ACPI_FAILURE(result)) { | ||
77 | pr_err("ACPI call to query Bluetooth presence failed"); | ||
78 | return -ENXIO; | ||
79 | } else if (!bt_present) { | ||
80 | pr_info("Bluetooth device not present\n"); | ||
81 | return -ENODEV; | ||
82 | } | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int toshiba_bluetooth_status(acpi_handle handle) | ||
88 | { | ||
89 | acpi_status result; | ||
90 | u64 status; | ||
91 | |||
92 | result = acpi_evaluate_integer(handle, "BTST", NULL, &status); | ||
93 | if (ACPI_FAILURE(result)) { | ||
94 | pr_err("Could not get Bluetooth device status\n"); | ||
95 | return -ENXIO; | ||
96 | } | ||
97 | |||
98 | pr_info("Bluetooth status %llu\n", status); | ||
99 | |||
100 | return status; | ||
101 | } | ||
60 | 102 | ||
61 | static int toshiba_bluetooth_enable(acpi_handle handle) | 103 | static int toshiba_bluetooth_enable(acpi_handle handle) |
62 | { | 104 | { |
63 | acpi_status res1, res2; | 105 | acpi_status result; |
64 | u64 result; | 106 | bool killswitch; |
107 | bool powered; | ||
108 | bool plugged; | ||
109 | int status; | ||
65 | 110 | ||
66 | /* | 111 | /* |
67 | * Query ACPI to verify RFKill switch is set to 'on'. | 112 | * Query ACPI to verify RFKill switch is set to 'on'. |
68 | * If not, we return silently, no need to report it as | 113 | * If not, we return silently, no need to report it as |
69 | * an error. | 114 | * an error. |
70 | */ | 115 | */ |
71 | res1 = acpi_evaluate_integer(handle, "BTST", NULL, &result); | 116 | status = toshiba_bluetooth_status(handle); |
72 | if (ACPI_FAILURE(res1)) | 117 | if (status < 0) |
73 | return res1; | 118 | return status; |
74 | if (!(result & 0x01)) | 119 | |
75 | return 0; | 120 | killswitch = (status & BT_KILLSWITCH_MASK) ? true : false; |
121 | powered = (status & BT_POWER_MASK) ? true : false; | ||
122 | plugged = (status & BT_PLUGGED_MASK) ? true : false; | ||
76 | 123 | ||
77 | pr_info("Re-enabling Toshiba Bluetooth\n"); | 124 | if (!killswitch) |
78 | res1 = acpi_evaluate_object(handle, "AUSB", NULL, NULL); | ||
79 | res2 = acpi_evaluate_object(handle, "BTPO", NULL, NULL); | ||
80 | if (!ACPI_FAILURE(res1) || !ACPI_FAILURE(res2)) | ||
81 | return 0; | 125 | return 0; |
126 | /* | ||
127 | * This check ensures to only enable the device if it is powered | ||
128 | * off or detached, as some recent devices somehow pass the killswitch | ||
129 | * test, causing a loop enabling/disabling the device, see bug 93911. | ||
130 | */ | ||
131 | if (powered || plugged) | ||
132 | return 0; | ||
133 | |||
134 | result = acpi_evaluate_object(handle, "AUSB", NULL, NULL); | ||
135 | if (ACPI_FAILURE(result)) { | ||
136 | pr_err("Could not attach USB Bluetooth device\n"); | ||
137 | return -ENXIO; | ||
138 | } | ||
139 | |||
140 | result = acpi_evaluate_object(handle, "BTPO", NULL, NULL); | ||
141 | if (ACPI_FAILURE(result)) { | ||
142 | pr_err("Could not power ON Bluetooth device\n"); | ||
143 | return -ENXIO; | ||
144 | } | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int toshiba_bluetooth_disable(acpi_handle handle) | ||
150 | { | ||
151 | acpi_status result; | ||
152 | |||
153 | result = acpi_evaluate_object(handle, "BTPF", NULL, NULL); | ||
154 | if (ACPI_FAILURE(result)) { | ||
155 | pr_err("Could not power OFF Bluetooth device\n"); | ||
156 | return -ENXIO; | ||
157 | } | ||
82 | 158 | ||
83 | pr_warn("Failed to re-enable Toshiba Bluetooth\n"); | 159 | result = acpi_evaluate_object(handle, "DUSB", NULL, NULL); |
160 | if (ACPI_FAILURE(result)) { | ||
161 | pr_err("Could not detach USB Bluetooth device\n"); | ||
162 | return -ENXIO; | ||
163 | } | ||
84 | 164 | ||
85 | return -ENODEV; | 165 | return 0; |
86 | } | 166 | } |
87 | 167 | ||
88 | static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event) | 168 | static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event) |
@@ -99,23 +179,18 @@ static int toshiba_bt_resume(struct device *dev) | |||
99 | 179 | ||
100 | static int toshiba_bt_rfkill_add(struct acpi_device *device) | 180 | static int toshiba_bt_rfkill_add(struct acpi_device *device) |
101 | { | 181 | { |
102 | acpi_status status; | 182 | int result; |
103 | u64 bt_present; | ||
104 | int result = -ENODEV; | ||
105 | 183 | ||
106 | /* | 184 | result = toshiba_bluetooth_present(device->handle); |
107 | * Some Toshiba laptops may have a fake TOS6205 device in | 185 | if (result) |
108 | * their ACPI BIOS, so query the _STA method to see if there | 186 | return result; |
109 | * is really anything there, before trying to enable it. | ||
110 | */ | ||
111 | status = acpi_evaluate_integer(device->handle, "_STA", NULL, | ||
112 | &bt_present); | ||
113 | 187 | ||
114 | if (!ACPI_FAILURE(status) && bt_present) { | 188 | pr_info("Toshiba ACPI Bluetooth device driver\n"); |
115 | pr_info("Detected Toshiba ACPI Bluetooth device - " | 189 | |
116 | "installing RFKill handler\n"); | 190 | /* Enable the BT device */ |
117 | result = toshiba_bluetooth_enable(device->handle); | 191 | result = toshiba_bluetooth_enable(device->handle); |
118 | } | 192 | if (result) |
193 | return result; | ||
119 | 194 | ||
120 | return result; | 195 | return result; |
121 | } | 196 | } |
@@ -123,7 +198,7 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device) | |||
123 | static int toshiba_bt_rfkill_remove(struct acpi_device *device) | 198 | static int toshiba_bt_rfkill_remove(struct acpi_device *device) |
124 | { | 199 | { |
125 | /* clean up */ | 200 | /* clean up */ |
126 | return 0; | 201 | return toshiba_bluetooth_disable(device->handle); |
127 | } | 202 | } |
128 | 203 | ||
129 | module_acpi_driver(toshiba_bt_rfkill_driver); | 204 | module_acpi_driver(toshiba_bt_rfkill_driver); |
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 737e56d46f61..aac47573f9ed 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c | |||
@@ -45,7 +45,6 @@ MODULE_LICENSE("GPL"); | |||
45 | 45 | ||
46 | #define ACPI_WMI_CLASS "wmi" | 46 | #define ACPI_WMI_CLASS "wmi" |
47 | 47 | ||
48 | static DEFINE_MUTEX(wmi_data_lock); | ||
49 | static LIST_HEAD(wmi_block_list); | 48 | static LIST_HEAD(wmi_block_list); |
50 | 49 | ||
51 | struct guid_block { | 50 | struct guid_block { |
@@ -240,10 +239,10 @@ static bool find_guid(const char *guid_string, struct wmi_block **out) | |||
240 | if (memcmp(block->guid, guid_input, 16) == 0) { | 239 | if (memcmp(block->guid, guid_input, 16) == 0) { |
241 | if (out) | 240 | if (out) |
242 | *out = wblock; | 241 | *out = wblock; |
243 | return 1; | 242 | return true; |
244 | } | 243 | } |
245 | } | 244 | } |
246 | return 0; | 245 | return false; |
247 | } | 246 | } |
248 | 247 | ||
249 | static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) | 248 | static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) |