These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / platform / x86 / toshiba_bluetooth.c
1 /*
2  * Toshiba Bluetooth Enable Driver
3  *
4  * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com>
5  * Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com>
6  *
7  * Thanks to Matthew Garrett for background info on ACPI innards which
8  * normal people aren't meant to understand :-)
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/types.h>
21 #include <linux/acpi.h>
22 #include <linux/rfkill.h>
23
24 #define BT_KILLSWITCH_MASK      0x01
25 #define BT_PLUGGED_MASK         0x40
26 #define BT_POWER_MASK           0x80
27
28 MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
29 MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
30 MODULE_LICENSE("GPL");
31
32 struct toshiba_bluetooth_dev {
33         struct acpi_device *acpi_dev;
34         struct rfkill *rfk;
35
36         bool killswitch;
37         bool plugged;
38         bool powered;
39 };
40
41 static int toshiba_bt_rfkill_add(struct acpi_device *device);
42 static int toshiba_bt_rfkill_remove(struct acpi_device *device);
43 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
44
45 static const struct acpi_device_id bt_device_ids[] = {
46         { "TOS6205", 0},
47         { "", 0},
48 };
49 MODULE_DEVICE_TABLE(acpi, bt_device_ids);
50
51 #ifdef CONFIG_PM_SLEEP
52 static int toshiba_bt_resume(struct device *dev);
53 #endif
54 static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume);
55
56 static struct acpi_driver toshiba_bt_rfkill_driver = {
57         .name =         "Toshiba BT",
58         .class =        "Toshiba",
59         .ids =          bt_device_ids,
60         .ops =          {
61                                 .add =          toshiba_bt_rfkill_add,
62                                 .remove =       toshiba_bt_rfkill_remove,
63                                 .notify =       toshiba_bt_rfkill_notify,
64                         },
65         .owner =        THIS_MODULE,
66         .drv.pm =       &toshiba_bt_pm,
67 };
68
69 static int toshiba_bluetooth_present(acpi_handle handle)
70 {
71         acpi_status result;
72         u64 bt_present;
73
74         /*
75          * Some Toshiba laptops may have a fake TOS6205 device in
76          * their ACPI BIOS, so query the _STA method to see if there
77          * is really anything there.
78          */
79         result = acpi_evaluate_integer(handle, "_STA", NULL, &bt_present);
80         if (ACPI_FAILURE(result)) {
81                 pr_err("ACPI call to query Bluetooth presence failed");
82                 return -ENXIO;
83         } else if (!bt_present) {
84                 pr_info("Bluetooth device not present\n");
85                 return -ENODEV;
86         }
87
88         return 0;
89 }
90
91 static int toshiba_bluetooth_status(acpi_handle handle)
92 {
93         acpi_status result;
94         u64 status;
95
96         result = acpi_evaluate_integer(handle, "BTST", NULL, &status);
97         if (ACPI_FAILURE(result)) {
98                 pr_err("Could not get Bluetooth device status\n");
99                 return -ENXIO;
100         }
101
102         return status;
103 }
104
105 static int toshiba_bluetooth_enable(acpi_handle handle)
106 {
107         acpi_status result;
108
109         result = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
110         if (ACPI_FAILURE(result)) {
111                 pr_err("Could not attach USB Bluetooth device\n");
112                 return -ENXIO;
113         }
114
115         result = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
116         if (ACPI_FAILURE(result)) {
117                 pr_err("Could not power ON Bluetooth device\n");
118                 return -ENXIO;
119         }
120
121         return 0;
122 }
123
124 static int toshiba_bluetooth_disable(acpi_handle handle)
125 {
126         acpi_status result;
127
128         result = acpi_evaluate_object(handle, "BTPF", NULL, NULL);
129         if (ACPI_FAILURE(result)) {
130                 pr_err("Could not power OFF Bluetooth device\n");
131                 return -ENXIO;
132         }
133
134         result = acpi_evaluate_object(handle, "DUSB", NULL, NULL);
135         if (ACPI_FAILURE(result)) {
136                 pr_err("Could not detach USB Bluetooth device\n");
137                 return -ENXIO;
138         }
139
140         return 0;
141 }
142
143 /* Helper function */
144 static int toshiba_bluetooth_sync_status(struct toshiba_bluetooth_dev *bt_dev)
145 {
146         int status;
147
148         status = toshiba_bluetooth_status(bt_dev->acpi_dev->handle);
149         if (status < 0) {
150                 pr_err("Could not sync bluetooth device status\n");
151                 return status;
152         }
153
154         bt_dev->killswitch = (status & BT_KILLSWITCH_MASK) ? true : false;
155         bt_dev->plugged = (status & BT_PLUGGED_MASK) ? true : false;
156         bt_dev->powered = (status & BT_POWER_MASK) ? true : false;
157
158         pr_debug("Bluetooth status %d killswitch %d plugged %d powered %d\n",
159                  status, bt_dev->killswitch, bt_dev->plugged, bt_dev->powered);
160
161         return 0;
162 }
163
164 /* RFKill handlers */
165 static int bt_rfkill_set_block(void *data, bool blocked)
166 {
167         struct toshiba_bluetooth_dev *bt_dev = data;
168         int ret;
169
170         ret = toshiba_bluetooth_sync_status(bt_dev);
171         if (ret)
172                 return ret;
173
174         if (!bt_dev->killswitch)
175                 return 0;
176
177         if (blocked)
178                 ret = toshiba_bluetooth_disable(bt_dev->acpi_dev->handle);
179         else
180                 ret = toshiba_bluetooth_enable(bt_dev->acpi_dev->handle);
181
182         return ret;
183 }
184
185 static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
186 {
187         struct toshiba_bluetooth_dev *bt_dev = data;
188
189         if (toshiba_bluetooth_sync_status(bt_dev))
190                 return;
191
192         /*
193          * Note the Toshiba Bluetooth RFKill switch seems to be a strange
194          * fish. It only provides a BT event when the switch is flipped to
195          * the 'on' position. When flipping it to 'off', the USB device is
196          * simply pulled away underneath us, without any BT event being
197          * delivered.
198          */
199         rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
200 }
201
202 static const struct rfkill_ops rfk_ops = {
203         .set_block = bt_rfkill_set_block,
204         .poll = bt_rfkill_poll,
205 };
206
207 /* ACPI driver functions */
208 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
209 {
210         struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
211
212         if (toshiba_bluetooth_sync_status(bt_dev))
213                 return;
214
215         rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
216 }
217
218 #ifdef CONFIG_PM_SLEEP
219 static int toshiba_bt_resume(struct device *dev)
220 {
221         struct toshiba_bluetooth_dev *bt_dev;
222         int ret;
223
224         bt_dev = acpi_driver_data(to_acpi_device(dev));
225
226         ret = toshiba_bluetooth_sync_status(bt_dev);
227         if (ret)
228                 return ret;
229
230         rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
231
232         return 0;
233 }
234 #endif
235
236 static int toshiba_bt_rfkill_add(struct acpi_device *device)
237 {
238         struct toshiba_bluetooth_dev *bt_dev;
239         int result;
240
241         result = toshiba_bluetooth_present(device->handle);
242         if (result)
243                 return result;
244
245         pr_info("Toshiba ACPI Bluetooth device driver\n");
246
247         bt_dev = kzalloc(sizeof(*bt_dev), GFP_KERNEL);
248         if (!bt_dev)
249                 return -ENOMEM;
250         bt_dev->acpi_dev = device;
251         device->driver_data = bt_dev;
252         dev_set_drvdata(&device->dev, bt_dev);
253
254         result = toshiba_bluetooth_sync_status(bt_dev);
255         if (result) {
256                 kfree(bt_dev);
257                 return result;
258         }
259
260         bt_dev->rfk = rfkill_alloc("Toshiba Bluetooth",
261                                    &device->dev,
262                                    RFKILL_TYPE_BLUETOOTH,
263                                    &rfk_ops,
264                                    bt_dev);
265         if (!bt_dev->rfk) {
266                 pr_err("Unable to allocate rfkill device\n");
267                 kfree(bt_dev);
268                 return -ENOMEM;
269         }
270
271         rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
272
273         result = rfkill_register(bt_dev->rfk);
274         if (result) {
275                 pr_err("Unable to register rfkill device\n");
276                 rfkill_destroy(bt_dev->rfk);
277                 kfree(bt_dev);
278         }
279
280         return result;
281 }
282
283 static int toshiba_bt_rfkill_remove(struct acpi_device *device)
284 {
285         struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
286
287         /* clean up */
288         if (bt_dev->rfk) {
289                 rfkill_unregister(bt_dev->rfk);
290                 rfkill_destroy(bt_dev->rfk);
291         }
292
293         kfree(bt_dev);
294
295         return toshiba_bluetooth_disable(device->handle);
296 }
297
298 module_acpi_driver(toshiba_bt_rfkill_driver);