aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/toshiba_bluetooth.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-26 16:44:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-26 16:44:46 -0400
commit78d425677217b655ed36c492a070b5002832fc73 (patch)
treea178a3bf773027f3a70ecec1ad6f9d35074e4263 /drivers/platform/x86/toshiba_bluetooth.c
parent36a8032d77649430f5ef11fbf0df2bb026be0b04 (diff)
parent358d6a2c3ecae2b22c7d7e61f9d5672557446dfb (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 ...
Diffstat (limited to 'drivers/platform/x86/toshiba_bluetooth.c')
-rw-r--r--drivers/platform/x86/toshiba_bluetooth.c133
1 files changed, 104 insertions, 29 deletions
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
28MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>"); 33MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
29MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver"); 34MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
30MODULE_LICENSE("GPL"); 35MODULE_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
65static 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
87static 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
61static int toshiba_bluetooth_enable(acpi_handle handle) 103static 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
149static 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
88static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event) 168static 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
100static int toshiba_bt_rfkill_add(struct acpi_device *device) 180static 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)
123static int toshiba_bt_rfkill_remove(struct acpi_device *device) 198static 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
129module_acpi_driver(toshiba_bt_rfkill_driver); 204module_acpi_driver(toshiba_bt_rfkill_driver);